强制布局拖动行为,在缩放时进行转换,但拖动时没有转换 [英] Force layout drag behaviour with transition on zoom but no transition on drag

查看:309
本文介绍了强制布局拖动行为,在缩放时进行转换,但拖动时没有转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为这个问题很容易。我有这个网站为您代表我的意思: http://arda-maps.org/familytree / 因此,如果您在屏幕上添加了一些人,您可以拖动缩放视图。



缩放完全正常。缩放的持续时间很大。但我不喜欢拖动时的时间,并希望禁用它只是在那里。基本上这是代码:

  g.transition()。duration(450).attr(transform,translate + zoombuttonTranslate +)scale(+ zoombuttonScale +)); 

所以问题是如何禁用拖动事件的过渡/

解决方案

第一阶段



这是关闭...
只需要验证它将在节点上的拖动行为玩得很好。



Stategy




  • 使用 d3.event.sourceEvent.type 检查mousemove

  • 使用 d3.transform

  • 转换翻译缩放 > b $ b

      var width = 600,height = 200-16,margin = {top:25,right:5,bottom:5,left:5},w = width -  margin.left  -  margin.right,h = height  -  margin.top  -  margin.bottom,zoom = d3.behavior.zoom()。scaleExtent([0.4,4]).on(zoom,zoomed),svg = d3.select(#viz)。attr({width:width,height:height}).append(g).attr(transform,translate(+ margin.left + margin.top +)).call(zoom),transText = svg.append(text).text(transform = translate(margin.left,margin.top)).style(fill #5c5c5c).attr(dy,-.35em)surface = svg.append(rect).attr({width:w,height:h}).style({pointer-events: all,fill:#ccc,stroke-width:3,stroke:#fff}),surfaceText = svg.append(text).text(pointer-events:all ).style(fill,#5c5c5c).attr({dy:1em,dx:.2em})content = svg.append(g)。attr ,content).attr(transform,translate(0,0)),contentText = content.append(text).text(transform = translate(d3.event.translate) .event.scale)).style(fill,#5c5c5c).attr({dy:50,dx:20})content.selectAll(rect).data [[20 ,{60},[140,60]]).enter()。append(rect).attr({height:50,width:50} :#ccc}).each(function(d){d3.select(this).attr({x:d [0],y:d [1] }); function zoomStart(){} function zoomed(){return d3.event.sourceEvent.buttons? zoomDrag.call(this):zoomScale.call(this)} function zoomDrag(){var t = d3.transform(content.attr(transform)); t.translate = d3.event.translate; content.attr(transform,t.toString()); } function zoomScale(){var t = d3.transform(content.attr(transform)); t.translate = d3.event.translate; t.scale = d3.event.scale; content.transition()。duration(450).attr(transform,t.toString()); }  

      svg {outline:1px solid#282f51; pointer-events:all; } g {outline:1px solid red; shape-rednering:geometricPrecision; }  

     < script src =https:// cdnjs .cloudflare.com / ajax / libs / d3 / 3.4.11 / d3.min.js>< / script>< svg id =viz>< / svg>  






    第二阶段



    合并FDG



    由于FDG必须位于画布容器内,因此必须停止节点级事件从传播到画布。这是在OP代码中通过使用自定义拖动行为,停止传播在 dragstart 并添加一些 force.drag 行为设置 d.fixed = true )。这是伟大的,如果你不介意失去一些 force.drag 功能像粘贴节点鼠标悬停。这是很好的捕获小,精力充沛的节点。所以,为了获得两个世界的最好的,你可以钩子 force.drag'行为。



    策略




    • 应用与第一阶段相同的原则,但对鼠标滚轮事件进行跨浏览器测试。

    • force.drag 添加到节点

    • force.drag 添加自定义行为

    • 仅修复 shift -drag (或 shift -dragend)

    • 如果触摸设备触摸> 1, / ul>

      最后两点允许固定节点在需要时轻松释放。



      force.drag钩子



        // hook force.drag行为
      var stdDragStart = force.drag()。on(dragstart.force);
      force.drag()
      .on(dragstart,function(d){
      //防止在节点上拖动画布
      d3.event.sourceEvent。 stopPropagation();
      stdDragStart.call(this,d);
      });



      工作示例



        //调试面板/////////////////////////////////////// ////////////////////////////////////// var alpha = d3.select(#alpha) .text(waiting ...),cog = d3.select(#wrapAlpha)。insert(i,#fdg)。classed(fa fa-cog fa-spin,true)。 datum({instID:null}),fdgInst = d3.select(#fdg); elapsedTime = ElapsedTime(#panel,{margin:0,padding:0}).message(function fps:'+ d3.format(> 8.3f)(1 / this.aveLap())}); elapsedTime.consoleOn = true; alpha.log = function(e,instID){elapsedTime.mark timestamp(); (d3.format(> 8.4f)(e.alpha)); fdgInst.text(fdg instance:+ instID);}; d3.select(#update)。on(click,function(){var dataSet = false; return function(){// fdg。 force.stop(); fdg(dataSets [(dataSet =!dataSet,+ dataSet)])}})()); ////////////////////// ////////////////////////////////////////////////// ////////////////// var dataSets = [{nodes:[{name:node1,r:10},{name: node2,r:10},{name:node3,r:30},{name:node4,r:15}源:2,target:0},{source:2,target:1},{source:2,target:3} name:node3,r:30},{name:node1,r:20} :node4,r:15},{name:node5,r:10},{name:node6,r:10} {source:2,target:0},{source:2,target:1},{source:2,target:3} target:4},{source:2,target:5}]}],svg = SVG({width:600,height:200-34,margin:{top:25,right:5,bottom :5,left:5}},#viz),fdg = FDG(svg,alpha.log); fdg(dataSets [0]); function SVG /在选择器元素中拖动上下文//如果height或width是NaN,则假定它是一个有效长度,但忽略margin var margin = size.margin || {top:0,right:0,bottom:0,left:0},unitW = isNaN(size.width),unitH = isNaN(size.height),w = unitW? size.width:size.width  -  margin.left  -  margin.right,h = unitH? size.height:size.height  -  margin.top  -  margin.bottom,zoomed = function(){return this},zoom = d3.behavior.zoom()。scaleExtent([0.4,4]).on(zoom ,svg = d3.select(selector).selectAll(svg)。data([[transform root),function(d,i,j){zoomed.call(this,d,i,j);} ]]); svg.enter()。append(svg); svg.attr({width:size.width,height:size.height}); var g = svg.selectAll(#zoom)。data(id),gEnter = g.enter()。append(g).attr(transform,translate(+ margin.left + + margin.top +).call(zoom).attr({class:outline,id:zoom}),zoomText = gEnter.append(text).text (margin.left,margin.top)).style(fill,#5c5c5c).attr(dy,-.35em),surface = gEnter.append(rect).attr {width:w,height:h}).style({pointer-events:all,fill:#ccc,stroke-width:3,stroke:#fff}) surfaceText = gEnter.append(text).text(pointer-events:none).style(fill,#5c5c5c).attr({dy:1em,dx: .2em}); g.h = h; g.w = w; g.onZoom = function(cb){zoomed = cb;}; return g;} function FDG(svg,tickLog){var instID = Date.now(); force = d3.layout.force().size([svg.w,svg.h]).charge(-1000).linkDistance(50).on(end,function(){// manage dead instances of force //只有当此实例是当前所有者时才会停止if(cog.datum()。instID!= instID)return true; cog.classed(fa-spin,false); elapsedTime.stop();})。 on(start,function(){//标记为活动并且标记insID以建立所有权cog.classed(fa-spin,true).datum()。instID = instID; elapsedTime.start );函数fdg(data){force .nodes(data.nodes).links(data.edges).on(tick,(function(instID){return function(e){if(tickLog)tickLog.call e,instID); lines.attr(x1,function(d){return d.source.x;})attr(y1,function(d){return d.source.y;})attr (x2,function(d){return d.target.x;})attr(y2,function(d){return d.target.y;}); node.attr (d){returntranslate(+ [dx,dy] +)});}})(instID)).start svg.onZoom(缩放); hookDrag(force.drag(),dragstart.force,function(d){//防止在节点上拖动画布var e = d3.event.sourceEvent; e.stopPropagation(); d.fixed = e .shiftKey || e.touches&&(e.touches.length> 1);}); hookDrag(force.drag(),dragend.force,function(d){//防止在节点上拖动画布var e = d3.event.sourceEvent; d.fixed = e.shiftKey || d。 fixed;}); var content = svg.selectAll(g#fdg)。data([data]); content.enter()。append(g)。attr({id:fdg,class:outline}); var contentText = content.selectAll(。contentText).data([transform = translate(d3.event.translate)scale(d3.event.scale)]).enter()。append(text)。 classed(contentText,true).text(id).style(fill,#5c5c5c).attr({dy:20,dx:20}); var lines = content.selectAll(。links).data(linksData),linesEnter = lines.enter().insert(line,d3.select(#nodes)?#nodes:null)。 attr(class,links).attr({stroke:steelblue,stroke-width:3}); var node = content.selectAll(#nodes).data(nodesData),nodesEnter = nodes.enter()。append(g).attr(id,nodes),node = nodes.selectAll .node).data(id),newNode = node.enter()。append(g).attr(class,node).call(force.drag),circles = newNode.append circle).attr({class:content}).attr(r,function(d){return dr}).style({fill:red,opacity:0.8}); lines.exit()。remove(); node.exit()。remove(); function nodesData(d){return [d.nodes]; } function linksData(d){return d.edges; } function hookDrag(target,event,hook){// hook force.drag behavior var stdDragStart = target.on(event); target.on(event,function(d){hook.call(this,d); stdDragStart.call(this,d);}); } function zoomed(){var e = d3.event.sourceEvent,isWheel = e&& ((e.type ==mousewheel)||(e.type ==wheel));力(α)。 return isWheel? zoomWheel.call(this):zoomInst.call(this)} function zoomInst(){var t = d3.transform(content.attr(transform)); t.translate = d3.event.translate; t.scale = d3.event.scale; content.attr(transform,t.toString()); } function zoomWheel(){var t = d3.transform(content.attr(transform)); t.translate = d3.event.translate; t.scale = d3.event.scale; content.transition()。duration(450).attr(transform,t.toString()); } fdg.force = force; }; return fdg} function id(d){return d;}  

        svg {outline:1px solid#282f51; pointer-events:all; overflow:visible; } g.outline {outline:1px solid red; } #panel div {display:inline-block; margin:0 .25em 3px 0; } #panel div div {white-space:pre; } div#inputDiv {white-space:normal; display:inline-block; } .node {cursor:default; } text {font-size:8px; }  

       < link rel =stylesheethref = https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css\"> ;<script src =https://cdnjs.cloudflare.com/ ajax / libs / d3 / 3.4.11 / d3.min.js>< / script>< script src =https://gitcdn.xyz/repo/cool-Blue/40e550b1507cca31b0bb/raw/b83ceb0f8b4a2b6256f079f5887fc5243baedd4f/elapsed %2520time%25201.0.js>< / script>< div id =panel> < div id =inputDiv> < input id =updatetype =buttonvalue =update> < / div> < div id =wrapAlpha> alpha:< div id =alpha>< / div> < / div> < div id =fdg>< / div>< div id =viz>< / div>  


      I think the question is very easy. I have this site for you for demontrating what I mean: http://arda-maps.org/familytree/ So if you add some persons there to the screen you are able to drag and zoom the view.

      The zooming is totally fine. The duration for zooming is great. But I don't like the duration when dragging and would like to disable it just there. Basically this is the code:

      g.transition().duration(450).attr("transform", "translate(" + zoombuttonTranslate + ")scale(" + zoombuttonScale + ")");
      

      So the question is how to disable the transition/duration just on the dragging event? Is this even possible somehow?

      解决方案

      Phase I

      I think this is close... It just needs to be verified that it will play nice with the drag behaviour on the nodes.

      Stategy

      • use d3.event.sourceEvent.type to check for mousemove
      • augment the current transform state using d3.transform
      • transition translate and scale for mouse wheel events and no transition for mouse button events

      Working example

      var width = 600, height = 200-16,
          margin = {top: 25, right: 5, bottom: 5, left: 5},
          w = width - margin.left - margin.right,
          h = height - margin.top - margin.bottom,
      
          zoom = d3.behavior.zoom().scaleExtent([0.4, 4])
            .on("zoom", zoomed),
          svg = d3.select("#viz").attr({width: width, height: height})
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
            .call(zoom),
          transText = svg.append("text")
            .text("transform = translate ( margin.left , margin.top )")
            .style("fill", "#5c5c5c")
            .attr("dy", "-.35em")
          surface = svg.append("rect")
            .attr({width: w, height: h})
            .style({"pointer-events": "all", fill: "#ccc", "stroke-width": 3, "stroke": "#fff"}),
          surfaceText = svg.append("text")
            .text("pointer-events: all")
            .style("fill", "#5c5c5c")
            .attr({"dy": "1em", "dx": ".2em"})
          content = svg.append("g").attr("id", "content")
            .attr("transform", "translate(0,0)"),
          contentText = content.append("text")
          .text("transform = translate ( d3.event.translate ) scale ( d3.event.scale )")
          .style("fill", "#5c5c5c")
          .attr({"dy": 50, "dx": 20})
          content.selectAll("rect")
            .data([[20,60],[140,60]])
            .enter().append("rect")
            .attr({height: 50, width: 50})
            .style({"stroke-width": 3, "stroke": "#ccc"})
            .each(function(d){
              d3.select(this).attr({x: d[0], y: d[1]});
            });
      
        function zoomStart(){
      
        }
        function zoomed(){
          return d3.event.sourceEvent.buttons ? zoomDrag.call(this) : zoomScale.call(this)
        }
        function zoomDrag(){
        var t = d3.transform(content.attr("transform"));
          t.translate = d3.event.translate;
          content.attr("transform", t.toString());
        }
        function zoomScale(){
          var t = d3.transform(content.attr("transform"));
          t.translate = d3.event.translate; t.scale = d3.event.scale;
          content.transition().duration(450).attr("transform", t.toString());
        }

      svg {
            outline: 1px solid #282f51;
            pointer-events: all;
          }
          g {
            outline: 1px solid red;
            shape-rednering: "geometricPrecision";
          }

      <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
      <svg id="viz"></svg>


      Phase II

      Incorporate an FDG

      Since the FDG must be inside the canvas container, it's necessary to stop node level events from propagating to the canvas. This was done in the OP code by using a custom drag behaviour, stopping propagation on dragstart and adding back some of the force.drag behaviour (plus setting d.fixed = true). This is great if you don't mind losing some of theforce.dragfeatures like sticking nodes on mouseover. This is nice for capturing small, energetic nodes though. So, in order to get the best of both worlds, you can hook theforce.drag` behaviour.

      Strategy

      • apply the same principles as in Phase I but do a cross-browser test for mouse wheel events.
      • add standard force.drag to the nodes
      • hook the force.drag to add custom behaviour
      • only fix nodes on shift-drag (or shift-dragend)
      • for touch devices, also fix nodes if touches > 1 at dragstart

      The last two points allow fixed nodes to be easily released if desired.

      force.drag hook

              //hook force.drag behaviour
              var stdDragStart = force.drag().on("dragstart.force");
              force.drag()
                  .on("dragstart", function(d){
                      //prevent dragging on the nodes from dragging the canvas
                      d3.event.sourceEvent.stopPropagation();
                      stdDragStart.call(this, d);
                  });
      

      Working example

      //debug panel/////////////////////////////////////////////////////////////////////////////
      var alpha = d3.select("#alpha").text("waiting..."),
      		cog = d3.select("#wrapAlpha").insert("i", "#fdg").classed("fa fa-cog fa-spin", true).datum({instID: null}),
      		fdgInst = d3.select("#fdg");
      elapsedTime = ElapsedTime("#panel", {margin: 0, padding: 0})
      	.message(function (id) {
      		return 'fps : ' + d3.format(" >8.3f")(1/this.aveLap())
      	});
      elapsedTime.consoleOn = true;
      
      alpha.log = function(e, instID) {
      	elapsedTime.mark().timestamp();
      	alpha.text(d3.format(" >8.4f")(e.alpha));
      	fdgInst.text("fdg instance: " + instID);
      };
      
      d3.select("#update").on("click", (function() {
      	var dataSet = false;
      	return function() {
      		//fdg.force.stop();
      		fdg(dataSets[(dataSet = !dataSet, +dataSet)])
      	}
      })());
      //////////////////////////////////////////////////////////////////////////////////////////
      var dataSets = [{
      				"nodes"    : [
      					{"name": "node1", "r": 10},
      					{"name": "node2", "r": 10},
      					{"name": "node3", "r": 30},
      					{"name": "node4", "r": 15}
      				],
      				"edges": [
      					{"source": 2, "target": 0},
      					{"source": 2, "target": 1},
      					{"source": 2, "target": 3}
      				]
      			},
      			{
      				"nodes":[
      					{"name": "node1", "r": 20},
      					{"name": "node2", "r": 10},
      					{"name": "node3", "r": 30},
      					{"name": "node4", "r": 15},
      					{"name": "node5", "r": 10},
      					{"name": "node6", "r": 10}
      				],
      				"edges":[
      					{"source": 2, "target": 0},
      					{"source": 2, "target": 1},
      					{"source": 2, "target": 3},
      					{"source": 2, "target": 4},
      					{"source": 2, "target": 5}
      				]
      			}
      		],
      		svg = SVG({width: 600, height: 200-34, margin: {top: 25, right: 5, bottom: 5, left: 5}}, "#viz"),
      		fdg = FDG(svg, alpha.log);
      
      fdg(dataSets[0]);
      
      function SVG (size, selector){
      	//delivers an svg background with zoom/drag context in the selector element
      	//if height or width is NaN, assume it is a valid length but ignore margin
      	var margin = size.margin || {top: 0, right: 0, bottom: 0, left: 0},
      			unitW = isNaN(size.width), unitH = isNaN(size.height),
      			w = unitW ? size.width : size.width - margin.left - margin.right,
      			h = unitH ? size.height : size.height - margin.top - margin.bottom,
      			zoomed = function(){return this},
      
      			zoom = d3.behavior.zoom().scaleExtent([0.4, 4])
      				.on("zoom", function(d, i, j){
      					zoomed.call(this, d, i, j);
      				}),
      
      			svg = d3.select(selector).selectAll("svg").data([["transform root"]]);
      			svg.enter().append("svg");
      			svg.attr({width: size.width, height: size.height});
      
      	var g = svg.selectAll("#zoom").data(id),
      			gEnter = g.enter().append("g")
      				.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
      				.call(zoom)
      				.attr({class: "outline", id: "zoom"}),
      			zoomText = gEnter.append("text")
      				.text("transform = translate ( margin.left , margin.top )")
      				.style("fill", "#5c5c5c")
      				.attr("dy", "-.35em"),
      			surface = gEnter.append("rect")
      				.attr({width: w, height: h})
      				.style({"pointer-events": "all", fill: "#ccc", "stroke-width": 3, "stroke": "#fff"}),
      			surfaceText = gEnter.append("text")
      				.text("pointer-events: none")
      				.style("fill", "#5c5c5c")
      				.attr({"dy": "1em", "dx": ".2em"});
      
      	g.h = h;
      	g.w = w;
      	g.onZoom = function(cb){zoomed = cb;};
      
      	return g;
      }
      function FDG (svg, tickLog) {
      	var instID = Date.now();
      	force = d3.layout.force()
      		.size([svg.w, svg.h])
      		.charge(-1000)
      		.linkDistance(50)
      		.on("end", function(){
      			// manage dead instances of force
      			// only stop if this instance is the current owner
      			if(cog.datum().instID != instID) return true;
      			cog.classed("fa-spin", false);
      			elapsedTime.stop();
      		})
      		.on("start", function(){
      			// mark as active and brand the insID to establish ownership
      			cog.classed("fa-spin", true).datum().instID = instID;
      			elapsedTime.start();
      		});
      
      	function fdg(data) {
      				force
      					.nodes(data.nodes)
      					.links(data.edges)
      					.on("tick", (function(instID) {
      						return function(e) {
      							if(tickLog) tickLog.call(this, e, instID);
      							lines.attr("x1", function(d) {
      								return d.source.x;
      							}).attr("y1", function(d) {
      								return d.source.y;
      							}).attr("x2", function(d) {
      								return d.target.x;
      							}).attr("y2", function(d) {
      								return d.target.y;
      							});
      							node.attr("transform", function(d) {
      								return "translate(" + [d.x, d.y] + ")"
      							});
      						}
      					})(instID))
      					.start();
      
      		svg.onZoom(zoomed);
      
      		hookDrag(force.drag(), "dragstart.force", function(d) {
      			// prevent dragging on the nodes from dragging the canvas
      			var e = d3.event.sourceEvent;
      			e.stopPropagation();
      			d.fixed = e.shiftKey || e.touches && (e.touches.length > 1);
      		});
      		hookDrag(force.drag(), "dragend.force", function(d) {
      			// prevent dragging on the nodes from dragging the canvas
      			var e = d3.event.sourceEvent;
      			d.fixed = e.shiftKey || d.fixed;
      		});
      
      		var content = svg.selectAll("g#fdg").data([data]);
      		content.enter().append("g").attr({"id": "fdg", class: "outline"});
      
      		var contentText = content.selectAll(".contentText")
      			.data(["transform = translate ( d3.event.translate ) scale ( d3.event.scale )"])
      			.enter().append("text").classed("contentText", true)
      			.text(id)
      			.style("fill", "#5c5c5c")
      			.attr({"dy": 20, "dx": 20});
      
      		var lines = content.selectAll(".links")
      					.data(linksData),
      				linesEnter = lines.enter()
      					.insert("line", d3.select("#nodes") ? "#nodes" : null)
      					.attr("class", "links")
      					.attr({stroke: "steelblue", "stroke-width": 3});
      		var nodes = content.selectAll("#nodes")
      					.data(nodesData),
      				nodesEnter = nodes.enter().append("g")
      					.attr("id", "nodes"),
      				node = nodes.selectAll(".node")
      					.data(id),
      				newNode = node.enter().append("g")
      					.attr("class", "node")
      					.call(force.drag),
      				circles = newNode.append("circle")
      					.attr({class: "content"})
      					.attr("r", function(d) {return d.r})
      					.style({"fill": "red", opacity: 0.8});
      
      		lines.exit().remove();
      		node.exit().remove();
      
      		function nodesData(d) {
      			return [d.nodes];
      		}
      
      		function linksData(d) {
      			return d.edges;
      		}
      
      		function hookDrag(target, event, hook) {
      			//hook force.drag behaviour
      			var stdDragStart = target.on(event);
      			target.on(event, function(d) {
      				hook.call(this, d);
      				stdDragStart.call(this, d);
      			});
      		}
      
      		function zoomed(){
      			var e = d3.event.sourceEvent,
      					isWheel = e && ((e.type == "mousewheel") || (e.type == "wheel"));
      			force.alpha(0.01);
      			return isWheel ? zoomWheel.call(this) : zoomInst.call(this)
      		}
      		function zoomInst(){
      			var t = d3.transform(content.attr("transform"));
      			t.translate = d3.event.translate; t.scale = d3.event.scale;
      			content.attr("transform", t.toString());
      		}
      		function zoomWheel(){
      			var t = d3.transform(content.attr("transform"));
      			t.translate = d3.event.translate; t.scale = d3.event.scale;
      			content.transition().duration(450).attr("transform", t.toString());
      		}
      
      		fdg.force = force;
      
      	};
      	return fdg
      
      }
      function id(d){return d;}

      svg {
            outline: 1px solid #282f51;
            pointer-events: all;
            overflow: visible;
          }
      
          g.outline {
            outline: 1px solid red;
          }
      
          #panel div {
            display: inline-block;
            margin: 0 .25em 3px 0; 
            
          }
          #panel div div {
            white-space: pre;
          }
          div#inputDiv {
            white-space: normal;
            display: inline-block;
          }
      
          .node {
            cursor: default;
          }
      
          text {
            font-size: 8px;
          }

      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css">
      <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
      <script src="https://gitcdn.xyz/repo/cool-Blue/40e550b1507cca31b0bb/raw/b83ceb0f8b4a2b6256f079f5887fc5243baedd4f/elapsed%2520time%25201.0.js"></script>
      <div id="panel">
        <div id="inputDiv">
          <input id="update" type="button" value="update">
        </div>
        <div id="wrapAlpha">alpha:
          <div id="alpha"></div>
        </div>
        <div id="fdg">
      </div>
      <div id="viz"></div>

      这篇关于强制布局拖动行为,在缩放时进行转换,但拖动时没有转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

      查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆