当前位置: 首页 > news >正文

中国建筑人才招聘网官网seo引擎优化外包

中国建筑人才招聘网官网,seo引擎优化外包,晋江网站建设哪家好,福州网站开发【趟坑记录】d3.zoom()的正确使用姿势 d3.v7 文章目录 【趟坑记录】d3.zoom()的正确使用姿势 d3.v7问题重现原因分析解决方案放缩平移写法特殊修改transform函数的写法 总结 在开发一个D3应用的时候遇到了一个 zoom相关的问题,记录解决思路与方案 问题重现 最近在…

【趟坑记录】d3.zoom()的正确使用姿势 @d3.v7

文章目录

  • 【趟坑记录】`d3.zoom()`的正确使用姿势 @d3.v7
      • 问题重现
      • 原因分析
      • 解决方案
        • 放缩平移写法
        • 特殊修改`'transform'`函数的写法
      • 总结

在开发一个D3应用的时候遇到了一个 zoom相关的问题,记录解决思路与方案

问题重现

最近在开发一个D3应用的时候遇到了一个zoom相关的问题,应用里有一个功能叫全景聚焦。我们都知道画布由两个标签组成(见实现autoZoom(),画布自适应放缩并居中@D3.js-v5),最外层的是固定视口<svg>,一般将zoom事件绑定在<svg>上;内层是具体的画布,是一个<g>标签,在<svg>中的放缩与平移操作都作用在<g>上,修改<g>transform属性。这么做是为了避免用户将<svg>元素拖动到窗口之外后丢失拖动焦点,无法将其拖回。而如果使<svg>不动,<g>被拖动,那么拖动焦点就不会丢失,用户将<g>元素移动至视口外后,还能将其拖回来。

我之前习惯这么写拖动平移:

const svg = d3.select('#viewport').attr('width', width).attr('height', height)
const g = svg.append('g').attr('id', 'container').attr('width', width).attr('height', height)svg.call(d3.zoom().on('zoom', (e) => {const transform = `translate(${e.transform.x},${e.transform.y}) scale(${e.transform.k})`g.attr('transform', transform)})
)

在一些业务场景中,往往需要对<g>元素进行特定的平移与放缩。如:自动缩放至视口中央,放大至当前的1.5倍。然而,在其他直接地方修改了<g>‘transform’属性后,如:

const offsetX = 10;
const offsetY = 10;
g.attr('transform',`translate(${offsetX},${offsetY})`

,问题就出现了,如下:

bugreproduce

可以看到,在设置了特定的'transform'后,再进行拖动,会出现瞬移。

原因分析

因为监听的zoom事件是通过e.transform来进行放缩的。而在修改<g>元素的‘transform’属性为一个特定值后,再进行拖动,会从上一次的e.tranform值开始修改,因此会出现错误。

举例说明:

  1. 用户拖动,e.transform的数值修改为了transform_1
  2. 有一个自动放缩函数autoZoom,将<g>'transform'修改为了transform_2
  3. 用户再次进行拖动,<g>'transform'会从transform_1开始修改,因此会出现从transform_2transform_1的瞬移。

解决方案

得知原因之后,解决方案也非常明了。就是在任何需要进行放缩平移的地方,都将transform进行缓存,下一次再需要进行放缩平移操作时,从上一次的transform开始进行更改即可。

一开始我想的解决方案是在每次鼠标拖动时都记录一个偏移量,但是这个偏移量比较难获取,心想d3这么大个库应该不至于用这么蠢的办法,应该有更好用的方案。

查了一下官方的API,发现了一个叫zoomTransform(node)的接口,这个接口传入的是一个HTML node,需要用d3.select(xx).node()来获得,可以获取这个node的放缩数据。官方文档是这么说的:

Internally, an element’s transform is stored as element.__zoom; however, you should use this method rather than accessing it directly. If the given node has no defined transform, returns the transform of the closest ancestor, or if none exists, the identity transformation


在内部,元素的变换存储为 element.__zoom;但是,您应该使用此方法(指的是zoomTransform)而不是直接访问它。如果给定节点没有定义的变换,则返回最近祖先的变换,或者如果不存在,则返回恒等变换。返回的变换表示以下形式的二维变换矩阵(略):

These properties should be considered read-only; instead of mutating a transform, use transform.scale and transform.translate to derive a new transform.


这些属性应被视为只读;使用transform.scale和transform.translate来派生新的变换,而不是改变变换。(下文将介绍如何派生新的变换)

进一步查看了源码,发现在svg.call(zoom)这个操作后,<svg>这个HTML node就会绑上一个__zoom 属性,这个__zoom属性记录的是transform参数,也就是我们对<svg>进行的放缩平移变换。为此我还特定打印了一下,发现确实如此:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YmbofakK-1689904577005)(/Users/zqqcee/Library/Application Support/typora-user-images/image-20230720100136154.png)]

那现在事情就变得很简单了,可以转变一下思路。之前我一直希望能够在autoZoom()之后,获得"zoom"事件的偏移量,使得我能够接着这个'transform'值修改。那么既然我无法获得偏移量,可以尝试在autoZoom()方法中不要直接修改<g>'transform'属性,而去修改<svg>.__zoom值。

放缩平移写法

在一开始时,使用d3.zoom()创建放缩对象zoom,并在任何时刻都使用<svg>call(zoom)修改放缩值。在绑定"zoom"事件时,因为<svg> callzoom,因此任何偏移量都会记录在<svg>,在修改<g>'transform'属性时,可以直接使用d3.zoomTransform(svg.node())来获得<svg>.__zoom来进行应用。

const svg = d3.select('body').append('svg');
const g = svg.append('g');
const zoom = d3.zoom().on('zoom',()=>{g.attr('transform', d3.zoomTransform(svg.node()));
})

特殊修改'transform'函数的写法

这里需要说明一下autoZoom()的写法,假设我们现在已经计算出了'transform'数值transformXtransformYk。现在需要修改<svg>__zoom属性为当前的'transform'数值。

查阅了官方文档,找到了可以使用的API:

  • d3.zoomIdentity。这个API可以创建一个新的'transform':{x:0,y:0,k:1},并允许使用transform.translate(x,y), transform.scale(k)对其进行更改。
  • selection.call(zoom.transform,new_transform);使用这个接口能够将<svg>.__zoom修改为new_transform

综上,代码为:

const new_transform = d3.zoomIdentity.translate(transformX, transformY).scale(k);
d3.select('svg').call(zoom.transform,new_transform);

总结

简而言之,任何对<g>的放缩与平移操作,都需要作用在<svg>上,并且使用<svg>.__zoom()来修改。

完整代码:

//zoom事件绑定
const svg = d3.select('body').append('svg');
const g = svg.append('g');
const zoom = d3.zoom().on('zoom',()=>{g.attr('transform', d3.zoomTransform(svg.node()));
})//需要修改特定transform的函数,以autoZoom为例
const autoZoom = (transformX,transformY,k) =>{const new_transform = d3.zoomIdentity.translate(transformX, transformY).scale(k);d3.select('svg').call(zoom.transform,new_transform);
}
http://www.dt0577.cn/news/8864.html

相关文章:

  • wordpress 根据id获取文章佛山优化推广
  • 触屏版网站开发精准推广的渠道有哪些
  • 金融行业网站建设方案最新国内重大新闻
  • 网站开发高级工程师专业石家庄疫情最新情况
  • 凡科网站开发国内新闻大事20条
  • 个人做网站流程图百度大数据查询怎么用
  • 广州微网站建设泰安百度推广代理
  • 网站开发怎么样营销推广策略有哪些
  • 网站建设计划书如何自己开发一个平台
  • 网站建设好销售吗交易平台
  • 设计找版面网站重庆可靠的关键词优化研发
  • 网站建设nayuwang关键词分类
  • 广告制作公司简介模板seo的优化原理
  • 广州番禺网站制作公司域名被墙检测
  • 辛集seo网站优化价格关键词优化搜索排名
  • 做漫画视频在线观看网站百度投诉电话人工客服24小时
  • 知名网站制作企业火星培训机构收费明细
  • 最新seo教程重庆seo网站
  • 新建网站怎样绑定域名长尾词seo排名
  • 深圳多彩科技集团有限公司北京seo服务销售
  • 快速搭建外贸网站苹果aso优化
  • 营销型网站建设推荐乐云seo网络优化seo
  • 驻马店logo设计公司广州seo网站排名
  • 电子商务网站开发相关技术搜索引擎优化的概念
  • 网站前置审批文件如何网上免费打广告
  • 中国做网站最好的公司重庆seo代理
  • 有一个专门做演讲的网站百度指数电脑版
  • 做游戏网站公司百度竞价推广代理
  • 企业网站建设与维护运营绍兴seo管理
  • 流程图 网站网络营销图片