【项目技术点总结之一】vue集成d3.js利用svg加载图片实现缩放拖拽功能

【项目技术点总结之一】vue集成d3.js利用svg加载图片实现缩放拖拽功能

  • 前言
    • 概述
    • 技术介绍
  • 实现过程
    • 插件安装
    • 引用组件
    • 初始化组件
    • 实现效果
  • 简单理解
    • 使用d3创建一个svg
    • 在svg中提添加元素
    • 函数使用
    • 使用总结
  • 说在最后

前言

概述

最近项目开发过程中,前端需要有一个图片预览的组件,支持图片放大、缩小、拖拽等地图的基本功能,并且需要考虑后期扩展,可以在预览过程中添加标注。最初觉得这得用操作地图的插件才可以搞定,但仅仅是图片预览,没必要这样处理,于是就选用的d3.js来实现这一功能,发现完全满足所有的需求。
项目用的前端还是vue+elementui全家桶的模式,发现elementui本身就有一个图片预览的组件,个人觉得不是特别好用,有感兴趣的人可以去看看。
vue项目图片预览组件:

  • 基于element-ui中自带的一个组件(el-image-viewer)
  • vue图片预览组件(viewerjs )

技术介绍

很多人对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

引用组件

  • 在组件(单vue文件)中引用
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);
    },
  },
};

至此,在页面中即可对应实现不同的业务了。

实现效果

【项目技术点总结之一】vue集成d3.js利用svg加载图片实现缩放拖拽功能_第1张图片
底图是一张png的图片,通过d3+svg加载之后,获取对应点的坐标生成数据,既可以实现相应的效果,顺便说一句,d3操作svg有很多方法,需要慢慢摸索,所以最好了解svg本身有的属性会事半功倍。

简单理解

基于从网上查询的资料结合开发中的思考,简单记录一下个人理解:

  • 使用svg加载图片,是因为svg会给图片建立一个坐标空间,所有绘制的图形都是基于这个坐标空间来处理。
  • 为什么要使用d3.js呢?svg虽然有坐标空间,不支持缩放拖拽等功能,且d3能在代码中操作svg,从而可以实现编程式的开发。
    有了以上两点,其实就不难看出为什么会这样去组合使用了,目前也在论证是否使用别的js库能达到同样的效果,以下就分别讲解下d3操作svg的一些思路:

使用d3创建一个svg

var svgContainer = d3.select("body").append("svg")
                                .attr("width",200)
   		                     .attr("width",200)
   		                     .style("border","1px solid black");

以上代码就是创建了一个200*200的svg面板。

在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也是一知半解,所以后续也会在慢慢深入。

你可能感兴趣的:(前端开发,d3.js,vue.js,svg)