如下图所示,在图片上做标记,如圆形、矩形等。
该demo实现画布在页面布局中缩放后居中显示,可拖拽、缩放、做标记说明。
项目下载地址:/zhangcw66/draw_mark
如粘贴以下代码,请安装zrender
<template><div class="draw-mark"><div id="canvas" style="height:710px;background-color:#F5F5F5"></div></div></template><script>import zrender from 'zrender'export default {name: 'DrawMark',data() {return {imgSrc: require('@/assets/timg.jpg'),markInfo: [[440, 260],[590, 360],[770, 370]],isShowPoint: true,zr: {},// zrender group实例group: {},imgWidth: 0, // 大图宽度imgHeight: 0, // 大图高度whRatio: 0, // 大图比例frameScale: 0, // 缩放比subSet: [], // 存放已经绘画完成的矩形框信息circle: {},scale: 1,scaleMax: 15, // 最大比例scaleMin: 0.5 // 最小比例}},mounted() {this.initCanvas()},methods: {// 初始化画布绘制图片initCanvas() {const vm = this// 获取放置画布的元素const container = document.getElementById('canvas')// 初始化zr实例 zrender容器vm.zr = zrender.init(container)vm.group = new zrender.Group({slient: true // 组内子孙元素是否响应鼠标事件})// 创建图片对象const imgs = new Image()// 图片的src等于大图的地址imgs.crossOrigin = 'Anonymous'imgs.setAttribute('crossOrigin', 'Anonymous')imgs.src = this.imgSrcimgs.onerror = _ => {this.$message.error('图片加载失败!')return false}// 图片加载成功后imgs.onload = () => {const canvasWidth = container.clientWidthconst canvasHeight = container.clientHeight// 画布宽高比const canvasRatio = canvasWidth / canvasHeight// 图片的宽高比vm.whRatio = imgs.width / imgs.heightconst originalHeight = imgs.height// 图片相对于画布的尺寸进行调整// 如果图片的宽高比大于画布的宽高比if (vm.whRatio > canvasRatio) {imgs.width = canvasWidthimgs.height = imgs.width / vm.whRatio} else {imgs.height = canvasHeightimgs.width = imgs.height * vm.whRatio}// 对图片的宽高进行调整vm.imgWidth = imgs.widthvm.imgHeight = imgs.heightvm.frameScale = originalHeight / vm.imgHeight// 绘制图片const myImg = new zrender.Image({style: {image: this.imgSrc,x: 0,y: 0,width: vm.imgWidth,height: vm.imgHeight},z: 1,onmouseover: _ => {document.body.style.overflowY = 'hidden'},onmousewheel: _ => {document.body.style.overflowY = 'hidden'},onmouseout: item => {document.body.style.overflowY = ''}})// 将图片绘制至子节点中vm.group.add(myImg)// 调整图片在canvas中的位置if (vm.zr.getWidth() > vm.imgWidth) {vm.group.position[0] = (vm.zr.getWidth() - vm.imgWidth) / 2}if (vm.zr.getHeight() > vm.imgHeight) {vm.group.position[1] = (vm.zr.getHeight() - vm.imgHeight) / 2}// 将子节点添加至画布中vm.zr.add(vm.group)// 绘制markthis.markInfo.forEach((item, index) => {const opt = {stroke: '#f00',pointsSet: this.AssemblyData(item),id: index}vm.drawMark(opt)})// 调用鼠标的滚动事件vm.handleZoom()// 调用鼠标的拖拽事件vm.handleDrop()}},// 坐标框的转换AssemblyData(item) {let newArr = itemconst arr = newArr.map(item => {return Math.round(item /= this.frameScale)})return arr},// 画标记drawMark(opt) {const vm = this// vm.subSet = []vm.circle = new zrender.Circle({style: {stroke: opt.stroke || '#f00',fill: opt.stroke || '#f00',text: this.isShowPoint ? opt.id : null,textHeight: 6,textWidth: 6,fontWeight: 700,textPosition: [2, -11],textLineWidth: 2,textPadding: 1,fontSize: 12,textFill: opt.stroke || '#fff'},shape: {cx: opt.pointsSet[0],cy: opt.pointsSet[1],r: 3},hoverable: true,z: 2})vm.subSet.push(vm.circle)vm.group.add(vm.circle)},// 滚动缩放handleZoom() {const vm = this// 在画布子节点上监听鼠标滚轮事件 事件对象vm.group.on('mousewheel', ev => {// wheeldata 返回值说明:正值向上滚动,负值向下滚动 均为120的倍数 缩小20倍 结果可能是 +e.wheelDelta/20 或者是 -e.wheelData/20// 缩小20倍数 调整为10// 监听到鼠标再const e = (ev || event).wheelDelta / 60// scale原始的缩放比例是1 每次滚动在这个基础上加上或者减去滚轮缩放后的数据vm.scale += e// 调用缩放的函数 将缩放的比例传入vm.setScale(vm.scale)})},/** * 缩放 */setScale(scale, item) {if (scale > this.scaleMax) {scale = this.scaleMax} else if (scale < this.scaleMin) {scale = this.scaleMin}this.scale = scalethis.group.attr({scale: [this.scale, this.scale],origin: [this.zr.getWidth() / 5, this.zr.getHeight() / 5]})},// 拖拽handleDrop() {const vm = thisvm.zr.dragData = {drag: false,pos: [0, 0],group: null,target: null}vm.zr.on('mousedown', e => {// 画布拖拽的起始位置是 事件对象中的画布的坐标位置vm.zr.dragData.pos = [e.event.zrX, e.event.zrY]// 画布的拖拽目标vm.zr.dragData.target = e.targetif (e.target === undefined) {// !!!vm.zr.dragData.drag = false} else if (e.target.parent && e.target.parent.type === 'group') {vm.zr.dragData.drag = truevm.zr.dragData.group = e.target.parent}})// 鼠标抬起事件 关闭拖拽 将拖拽的目标元素设置为空vm.zr.on('mouseup', e => {vm.zr.dragData.drag = falsevm.zr.dragData.group = null})// 鼠标移出事件 关闭拖拽vm.zr.on('mouseout', e => {vm.zr.dragData.drag = falsevm.zr.dragData.group = null})// 鼠标移动事件vm.zr.on('mousemove', e => {if (vm.zr.dragData.drag !== true) returnconst new_pos = [e.event.zrX, e.event.zrY]if (vm.zr.dragData.group != null) {var pos = [new_pos[0] - vm.zr.dragData.pos[0],new_pos[1] - vm.zr.dragData.pos[1]]vm.zr.dragData.group.children().forEach(x => {x.position = [0, 0]})vm.zr.dragData.group.position[0] += pos[0]vm.zr.dragData.group.position[1] += pos[1]vm.zr.dragData.group.dirty()} else {// eslint-disable-next-line no-redeclarevar pos = [new_pos[0] - vm.zr.dragData.pos[0],new_pos[1] - vm.zr.dragData.pos[1]]vm.zr.storage.getDisplayList(true, true).forEach(x => {x.position[0] += pos[0]x.position[1] += pos[1]x.dirty()})}vm.zr.dragData.pos = [e.event.zrX, e.event.zrY]})}}}</script><style scoped>.draw-mark {padding: 30px;}</style>
如果觉得《canvas在图片上绘制标记 可拖拽 缩放 基于ZRender》对你有帮助,请点赞、收藏,并留下你的观点哦!