11

d3 ライブラリが提供するズーム機能を一時的に無効にする可能性を探しています。ズームが無効になっているときに現在のスケール/変換値を洞窟に保存し、ズームが再びアクティブになったときにズーム/変換値を設定しようとしました。残念ながら、これは機能しません。

これが私が作成したコード例です:

var savedTranslation = null;
var savedScale = null;

var body = d3.select("body");

var svg = body.append("svg");

var svgContainer = svg.append("svg:g");

var circle = svgContainer.append("svg:circle")
    .attr('cx', 100)
    .attr('cy', 100)
    .attr('r',30)
    .attr('fill', 'red');

circle.on('click', clickFn);

function clickFn(){
    if (circle.attr('fill') === 'red'){
        circle.attr('fill','blue')
    }
    else if (circle.attr('fill') === 'blue'){
        circle.attr('fill','red')
    }
}; 

svg.call(zoom = d3.behavior.zoom().on('zoom', redrawOnZoom)).on('dblclick.zoom', null);


 function redrawOnZoom(){
     if (circle.attr('fill') === 'red'){
         if (savedScale !== null){
             zoom.scale(savedScale)
             savedScale = null
         }
         if (savedTranslation !== null){
             zoom.translate(savedTranslation)
             savedTranslation = null
         }
         // the actual "zooming"
         svgContainer.attr('transform', 'translate(' + d3.event.translate + ')' + ' scale(' +         d3.event.scale + ')');
     }
     else {
         // save the current scales
         savedScale = zoom.scale()
         savedTranslation = zoom.translate()
     }
};

jsfiddle の実際の例を次に示します。

編集:

この誤った動作は、次の手順で再現できます。

  1. 円をクリックすると、色が青に変わり、ズームが機能しません
  2. マウス ホイールを 1 方向に数回使用して、ズームするようにします (ズームインなど)。
  3. 円をもう一度クリックすると、色が赤に変わり、ズームが再び有効になります
  4. マウス ホイールを使用すると、円が大きく/小さくなります
4

8 に答える 8

4

私は同じ問題に苦しんでいます。そして、現在のソリューションで見られるような慌てずに、ズームと翻訳を保存するソリューションを見つけました。

主な変更点は、「クリック」機能でズームと翻訳の保存/更新を実行することです。また、ズーム機能への参照を使用できるようにするには、ズーム動作の後にクリックを設定する必要があります。解決策は次のようになります。あなたの問題からの同じ定型文:

var savedTranslation = null;
var savedScale = null;

var body = d3.select("body");

var svg = body.append("svg");

var svgContainer = svg.append("svg:g");

var circle = svgContainer.append("svg:circle")
    .attr('cx', 100)
    .attr('cy', 100)
    .attr('r',30)
    .attr('fill', 'red');

次に、保存されたスケールと変換を管理せずにズーム機能を実行します。

svg.call(zoom = d3.behavior.zoom().on('zoom', redrawOnZoom)).on('dblclick.zoom', null);

function redrawOnZoom(){
     if (circle.attr('fill') === 'red'){
         // the actual "zooming"
         svgContainer.attr('transform', 'translate(' + zoom.translate() + ')' + ' scale(' + zoom.scale() + ')');
     }
};

最後に、スケールと変換の保存と設定を使用して、以下のクリック動作を添付します。

circle.on('click', clickFn);

function clickFn(){
    if (circle.attr('fill') === 'red'){
        circle.attr('fill','blue')
         if (savedScale === null){
             savedScale = zoom.scale();
         }
          if (savedTranslation === null){
             savedTranslation = zoom.translate();
         }      
    }
    else if (circle.attr('fill') === 'blue'){
        circle.attr('fill','red')
        if (savedScale !== null){
             zoom.scale(savedScale);
             savedScale = null;
         }
         if (savedTranslation !== null){
             zoom.translate(savedTranslation);
             savedTranslation = null;
         }
    }
}; 

ここに作業バージョンがあります: http://jsfiddle.net/cb3Zm/1/

ただし、ドラッグが発生したときにまだクリック イベントが発生するため、理想的とは思えませんが、まだ修正できていません。

于 2014-03-01T04:11:38.520 に答える
0

https://github.com/d3/d3-zoom/issues/156

const svg = d3.select(svgElement);
const zoom = d3.zoom();

function startZoomPan() {
  svg.call(zoom); // attach the zoom listeners
}

function stopZoomPan() {
  svg.on('.zoom', null); // remove the zoom listeners
}

mousemove ハンドラーはホット コードであるため、そこでの分岐が遅い

于 2021-03-02T11:43:38.707 に答える