Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何暂时禁用d3.js中的缩放功能_Javascript_Svg_D3.js_Zooming_Behavior - Fatal编程技术网

Javascript 如何暂时禁用d3.js中的缩放功能

Javascript 如何暂时禁用d3.js中的缩放功能,javascript,svg,d3.js,zooming,behavior,Javascript,Svg,D3.js,Zooming,Behavior,我正在寻找暂时禁用d3库提供的缩放功能的可能性。我尝试在禁用缩放时保存当前缩放/平移值,并在再次激活缩放时设置缩放/平移值。不幸的是,这行不通 下面是我创建的一个代码示例: var savedTranslation = null; var savedScale = null; var body = d3.select("body"); var svg = body.append("svg"); var svgContainer = svg.append("svg:g"); var cir

我正在寻找暂时禁用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()
     }
};
这是一个

编辑:

可通过以下步骤再现错误行为:

  • 单击圆圈,颜色变为蓝色,缩放不起作用
  • 在一个方向上多次使用鼠标滚轮,好像要进行缩放(例如放大)
  • 再次单击圆,颜色变为红色,缩放重新启用
  • 使用鼠标滚轮,圆圈将变大/变小

  • 我实现这一点的方法是使用一个全局标志,告诉您是否启用了缩放。然后,您只需检查是否在处理缩放的函数中设置了此标志。如果是,则该函数不执行任何操作。

    请参阅更新的小提琴:

    在这里,我在单击处理程序中重新分配了一个空的缩放行为

    function clickFn(){
        if (circle.attr('fill') === 'red'){
            circle.attr('fill','blue');
            svg.call( fake );
        }
        else if (circle.attr('fill') === 'blue'){
            circle.attr('fill','red');
            svg.call( zoom );
        }
    }; 
    
    我想有一个更好的解决方案,因为我的解决方案可能会导致内存泄漏

    与全局
    doZoom
    标志相比,它的优点是,即使您不更改视图,缩放行为仍会继续工作(例如设置
    d3.event.scale
    ),因此您不必保存和检查缩放和平移值。

    好的,问题出在

    else {
         // save the current scales
         savedScale = zoom.scale()
         savedTranslation = zoom.translate()
     }
    
    部分。每个事件都会调用这些值,而不是在圆改变颜色后才调用一次。因此,解决办法是:

    else {
         // save the current scales
         if (savedScale === null){
             savedScale = zoom.scale();
         }
          if (savedTranslation === null){
             savedTranslation = zoom.translate();
         }         
    
    现在它工作了!
    我认为这样做更漂亮

    function clickFn(){
        if (circle.attr('fill') === 'red'){
            circle.attr('fill','blue');
            savedScale = zoom.scale();
            savedTranslation = zoom.translate();
        }
        else if (circle.attr('fill') === 'blue'){
             circle.attr('fill','red');
             zoom.scale(savedScale);
             zoom.translate(savedTranslation);
        }
    }; 
    
    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(' + d3.event.translate + ')' + ' scale(' +         d3.event.scale + ')');
         }
    
    };
    

    我一直在努力解决同样的问题。而且,我找到了一个解决方案,它可以节省缩放和平移,而不会像当前解决方案那样出现跳跃

    主要更改是在“单击”功能中执行缩放和平移的保存/更新。为了使缩放功能的引用可用,必须在缩放行为之后设置单击。解决方案如下所示。与您的问题相同的样板文件:

    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;
             }
        }
    }; 
    
    以下是一个工作版本:


    但是,当发生拖动时,单击事件仍然会发生,这似乎不太理想,但我还没能解决它。

    我想在找到解决方案时赶上这个进度! 诀窍是在zoomstart和ZoomMend事件中重置缩放和平移

    var zoom = d3.behavior.zoom()
        .scaleExtent([1, 10])
        .on("zoomstart", zoomstart)
        .on("zoomend", zoomend)
        .on("zoom", zoomed);
    
    function zoomed() {
        if (circle.attr('fill') === 'red') {
            if (savedScale !== null){
                 zoom.scale(savedScale);
             }
             if (savedTranslation !== null){
                zoom.translate(savedTranslation);
             }
            svgContainer.attr('transform', 'translate(' +   d3.event.translate + ')' + ' scale(' +         d3.event.scale + ')');
        }
    }
    
    function zoomend () {
        if (circle.attr('fill') === 'red') {
            if (savedScale !== null){
                 zoom.scale(savedScale);
                 savedScale = null;
             }
             if (savedTranslation !== null){
                zoom.translate(savedTranslation);
                 savedTranslation = null;
             }
         }
    }
    
    function zoomstart (d) {
        if (circle.attr('fill') === 'red'){
             if (savedScale !== null){
                 zoom.scale(savedScale)
             }
             if (savedTranslation !== null){
                 zoom.translate(savedTranslation)
             }
         } else {
            if (savedScale === null) {
                savedScale = zoom.scale();
            }
            if (savedTranslation === null) {
                savedTranslation = zoom.translate();
            }
         }
    }
    

    我发现的最简单的方法是简单地禁用选择上的所有
    .zoom
    事件。您必须重新调用
    zoom
    以再次启用该行为

    if (zoomEnabled) {
        svg.call(zoom);
    } else {
        svg.on('.zoom', null);
    }
    

    const svg=d3.select(svgElement);
    const zoom=d3.zoom();
    函数startZoomPan(){
    调用(缩放);//附加缩放侦听器
    }
    函数stopZoomPan(){
    svg.on('.zoom',null);//删除缩放侦听器
    }
    

    mousemove处理程序是热代码,因此分支速度很慢

    谢谢您的建议。问题是,在我的项目中,我没有通过on('click',…)方法指定缩放行为。redrawOnZomm()函数应该根据圆的状态(颜色)进行操作。但是,我应该如何实现该函数“不做任何事情”,但我可以在某个点上重新启用缩放,并从我禁用它的点开始继续?我在可视化过程中出现了跳跃/移动,因为事件仍然会在鼠标滚轮/指针上做出反应。每次函数执行某项操作时,您只需保存缩放/平移的当前状态,然后在重新启用缩放时重新指定即可恢复。这就是我试图实现的。。。请您提供如何使用dr.js实现这一点的更详细信息?您可以在每次执行缩放功能时将
    zoom.translate
    zoom.scale
    的值保存在全局变量中,但如果禁用了缩放功能,则不会保存。然后,当重新启用缩放时,将这些值分配回缩放行为。这不是我在示例中所做的吗?问题是,缩放始终与鼠标滚轮/指针交互,因此d3.event.scale/translate值也会更改。我的问题是重新启用缩放后如何将这些值设置/还原为保存的值。显然,zoom.scale(savedScale)/zoom.translate(savedtransation)不起作用。这仍然只适用于缩放,对于平移,如果在禁用时拖动圆,重新启用它,然后再次拖动它,仍然会出现跳跃行为。zoomstart和ZoomMend事件已在最新版本之一中重命名为start和end