最近项目开发过程中,前端需要有一个图片预览的组件,支持图片放大、缩小、拖拽等地图的基本功能,并且需要考虑后期扩展,可以在预览过程中添加标注。最初觉得这得用操作地图的插件才可以搞定,但仅仅是图片预览,没必要这样处理,于是就选用的d3.js来实现这一功能,发现完全满足所有的需求。
项目用的前端还是vue+elementui全家桶的模式,发现elementui本身就有一个图片预览的组件,个人觉得不是特别好用,有感兴趣的人可以去看看。
vue项目图片预览组件:
很多人对d3.js的印象是一个前端的可视化库,与hightchart、echarts等差不多是一样,但是随着使用的进一步深入,就会发现d3的功能不仅于此。前面那chart类库局限的地方在于基本不可定制,即不同的图表必须严格按照文档来;而D3呢,你说了算,你想画出什么样的图,你说了算,自由度很大;当然最终还是需要根据项目需求选择。
回归正题,D3.js堪称SVG中的jQuery,你如果想用D3输出Canvas图也可以,但SVG图操作起来更加灵活,更加方便调试,基于这个思路,就萌生出使用d3.js操作svg,加载图片显示,实现其它组件不具备的能力。
npm install d3 --save-dev
需要注意的是,默认安装的应该是最新版本,其中有很多函数的调用逻辑会有变化,尤其是大版本不同的时候,本人就遇到因为版本问题很多函数不起作用的问题,所以最好注意安装后版本。
本人使用的5.5.0版本,不同版本说明d3.js版本说明,安装方法:
npm install [email protected] --save-dev
import * as d3 from "d3";
之后就可以在方法中直接使用。
2.注册到全局变量,在main.js中引入
import * as d3 from "d3";
Vue.prototype.$d3 = d3;
window.d3 = d3; //暂时设置为全局变量
import * as d3 from "d3";
export default {
name: "ViewImage",
data() {
return {
zoom_:null,
svg_:null,
container:null,
svg_width:500,
svg_height:500
};
},
mounted() {
this.hwInit();
this.svgInit();
},
created() {
},
methods: {
/** 动态获取svg面板的宽高*/
hwInit:function(){
this.svg_width = window.innerWidth-260;
this.svg_height = window.innerHeight -120;
},
/** 初始化svg面板*/
svgInit: function () {
this.zoom_ = d3.zoom().scaleExtent([0.5, 3]).on("zoom", this.zoomed);
this.svg_ = d3
.select("#img_content")
.append("svg")
.attr("width", this.svg_width)
.attr("height", this.svg_height)
.call(this.zoom_);
this.container = this.svg_.append("g").attr("fill","#ffffff");
},
/** 定义缩放的方法*/
zoomed: function (e) {
this.container.attr(
"transform",
"translate(" +
d3.event.transform.x +
"," +
d3.event.transform.y +
")scale(" +
d3.event.transform.k +
")"
);
},
/** 在svg上绘制图片*/
drawImg:function(bg_img){
this.container
.attr("class", "all")
.append("image")
.attr("xlink:href", bg_img)
.attr("x", "0")
.attr("y", "0")
.attr("width",this.svg_width)
.attr("height",this.svg_height);
},
},
};
至此,在页面中即可对应实现不同的业务了。
底图是一张png的图片,通过d3+svg加载之后,获取对应点的坐标生成数据,既可以实现相应的效果,顺便说一句,d3操作svg有很多方法,需要慢慢摸索,所以最好了解svg本身有的属性会事半功倍。
基于从网上查询的资料结合开发中的思考,简单记录一下个人理解:
var svgContainer = d3.select("body").append("svg")
.attr("width",200)
.attr("width",200)
.style("border","1px solid black");
以上代码就是创建了一个200*200的svg面板。
暂且较原生添加svg元素:
<svg width="50" height="50">
<circle cx="25" cy="25" r="25" fill="purple" />
svg>
使用d3.js添加svg元素:
var circleSelection = svgSelection.append("circle")
.attr("cx",25)
.attr("cy",25)
.attr("r",25)
.style("fill","purple");
实现了同样的效果,其中,.attr(“cx”,25)和.attr(“cy”,25)让我们可以设置SVG圆形的属性。
D3.js允许我们在.style()操作符和.attr()内部使用函数,比如:
var circleAttributes = circles
.attr("cx",function(d){return d;})
.attr("cy",function(d){return d;})
.attr("r",20)
.style("fill",function(d){return d;});
以此,我们就可以很轻松的实现以下定制化的需求。
当然此处只是大致分步骤梳理了下d3结合svg的用法,基于此添加上d3.js的事件、方法等即可灵活的定制开发。
d3.js中文文档【3.0】,虽然版本迭代会有很多更改,但是很多方法还是可以参考:
d3.js 3.0版本的中文翻译文档,
本文只是将自己实现的效果做了一下整理,深究之后才发现对d3.js的api以及使用还不是特别熟悉,仍然是停留在表面上,很多官方的api也是一知半解,所以后续也会在慢慢深入。