|
@@ -0,0 +1,696 @@
|
|
|
+<template>
|
|
|
+ <!-- 未做多语言 -->
|
|
|
+ <div class="mark-stage">
|
|
|
+ <vuescroll ref="canvasScroll">
|
|
|
+ <!-- canvas部分 -->
|
|
|
+ <div class="container-box">
|
|
|
+ <div id="container" @mousemove="canvasMouseMove" @mousedown="canvasMouseDown" @mouseup="canvasMouseUp"></div>
|
|
|
+ </div>
|
|
|
+ </vuescroll>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import Konva from 'konva'
|
|
|
+export default {
|
|
|
+ name: 'MarkCanvas',
|
|
|
+ props: {
|
|
|
+ // 当前鼠标操作类型
|
|
|
+ mouseStatus: {
|
|
|
+ type: String,
|
|
|
+ default: 'move',
|
|
|
+ required: true
|
|
|
+ },
|
|
|
+ //canvas主图(eg:学生作答数据)
|
|
|
+ bgImg: {
|
|
|
+ type: [String, Object],
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ //canvas绘制图片的数据(eg:添加表情包)
|
|
|
+ drawImgData: {
|
|
|
+ type: [String, Object],
|
|
|
+ default: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ stage: undefined,
|
|
|
+ orgLayer: undefined,
|
|
|
+ markLayer: undefined,
|
|
|
+ tr: undefined,
|
|
|
+ scaleDefault: 1,
|
|
|
+ maxScale: 5,
|
|
|
+ minScale: 0.2,
|
|
|
+ scaleStep: 0.2,
|
|
|
+ imgWidth: 0,
|
|
|
+ imgHeight: 0,
|
|
|
+ isMouseDown: false,
|
|
|
+ clickPoint: {
|
|
|
+ x: 0,
|
|
|
+ y: 0
|
|
|
+ },
|
|
|
+ // mouseStatus: 'move', //move:移动 rect:画矩形 resize:调整图形
|
|
|
+ resizeBefore: '',
|
|
|
+ rect: undefined,
|
|
|
+ oval: undefined,
|
|
|
+ arrow: undefined,
|
|
|
+ text: undefined,
|
|
|
+ line: undefined,
|
|
|
+ img: undefined,
|
|
|
+ isDltText: false,
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ uuid() {
|
|
|
+ function S4() {
|
|
|
+ return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
|
|
|
+ }
|
|
|
+ return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4())
|
|
|
+ },
|
|
|
+ move(index) {
|
|
|
+ this.activeIcon = index
|
|
|
+ this.mouseStatus = 'move'
|
|
|
+ },
|
|
|
+ drawImg(imgIndex) {
|
|
|
+ // this.activeIcon = imgIndex
|
|
|
+ // this.curImg = new Image()
|
|
|
+ // this.curImg.src = this.imgs[imgIndex]
|
|
|
+ // this.curImg.onload = () => {
|
|
|
+ // this.mouseStatus = 'img'
|
|
|
+ // this.startImg({ x: 100, y: 100 })
|
|
|
+ // }
|
|
|
+ },
|
|
|
+ startImg(current) {
|
|
|
+ let _this = this
|
|
|
+ this.img = new Konva.Image({
|
|
|
+ id: this.uuid(),
|
|
|
+ draggable: false,
|
|
|
+ strokeScaleEnabled: false,
|
|
|
+ image: _this.curImg,
|
|
|
+ width: 80,
|
|
|
+ height: 80,
|
|
|
+ x: current.x,
|
|
|
+ y: current.y
|
|
|
+ })
|
|
|
+ // 监听点击事件设置选中状态
|
|
|
+ this.img.on('click', (evt) => {
|
|
|
+ _this.resizeBefore = _this.mouseStatus == 'resize' ? _this.resizeBefore : _this.mouseStatus//记录resize之前的状态
|
|
|
+ _this.mouseStatus = 'resize'
|
|
|
+ evt.target.draggable(true)
|
|
|
+ evt.cancelBubble = true //阻止事件冒泡
|
|
|
+ _this.tr.nodes([evt.target])
|
|
|
+ _this.markLayer.add(_this.tr)
|
|
|
+ })
|
|
|
+ // 优化一些绘制逻辑
|
|
|
+ this.img.on('mouseout', (evt) => {
|
|
|
+ evt.cancelBubble = true //阻止事件冒泡
|
|
|
+ evt.target.draggable(false)
|
|
|
+ let nodes = _this.tr.nodes()
|
|
|
+ if (_this.mouseStatus == 'resize' && nodes.length == 0) _this.mouseStatus = _this.resizeBefore
|
|
|
+ })
|
|
|
+ // this.img.zIndex(1)
|
|
|
+ this.markLayer.add(this.img)
|
|
|
+ this.stage.add(this.markLayer)
|
|
|
+ this.img = null
|
|
|
+ },
|
|
|
+ drawText(index) {
|
|
|
+ this.activeIcon = index
|
|
|
+ this.mouseStatus = 'text'
|
|
|
+ },
|
|
|
+ startText(current) {
|
|
|
+ let _this = this
|
|
|
+ let nodes = this.tr.nodes()
|
|
|
+ if (nodes.length > 0) return
|
|
|
+ if (!this.text) {
|
|
|
+ this.text = new Konva.Text({
|
|
|
+ id: this.uuid(),
|
|
|
+ fontSize: 16,
|
|
|
+ text: '',
|
|
|
+ fill: 'red',
|
|
|
+ lineHeight: 1.5,
|
|
|
+ width: 180,
|
|
|
+ height: 30,
|
|
|
+ x: _this.clickPoint.x / _this.scaleDefault,
|
|
|
+ y: _this.clickPoint.y / _this.scaleDefault,
|
|
|
+ draggable: false
|
|
|
+ })
|
|
|
+ // 监听点击事件设置选中状态
|
|
|
+ this.text.on('click', (evt) => {
|
|
|
+ _this.resizeBefore = _this.mouseStatus == 'resize' ? _this.resizeBefore : _this.mouseStatus//记录resize之前的状态
|
|
|
+ _this.mouseStatus = 'resize'
|
|
|
+ evt.target.draggable(true)
|
|
|
+ evt.cancelBubble = true //阻止事件冒泡
|
|
|
+ _this.tr.nodes([evt.target])
|
|
|
+ _this.markLayer.add(_this.tr)
|
|
|
+ })
|
|
|
+ this.text.on('mouseout', (evt) => {
|
|
|
+ evt.cancelBubble = true //阻止事件冒泡
|
|
|
+ evt.target.draggable(false)
|
|
|
+ let nodes = _this.tr.nodes()
|
|
|
+ if (_this.mouseStatus == 'resize' && nodes.length == 0) _this.mouseStatus = _this.resizeBefore
|
|
|
+ })
|
|
|
+ this.text.on('dblclick dbltap', (evt) => {
|
|
|
+ let nodes = _this.tr.nodes()
|
|
|
+ if (nodes && nodes.length > 0) {
|
|
|
+ let text = nodes[0]
|
|
|
+ let textPosition = text.getAbsolutePosition()
|
|
|
+ let stageBox = _this.stage.container().getBoundingClientRect()
|
|
|
+ let areaPosition = {
|
|
|
+ x: stageBox.left + textPosition.x,
|
|
|
+ y: stageBox.top + textPosition.y,
|
|
|
+ }
|
|
|
+ let textarea = document.createElement('textarea');
|
|
|
+ document.body.appendChild(textarea)
|
|
|
+
|
|
|
+ textarea.value = text.text()
|
|
|
+ textarea.style.position = 'absolute'
|
|
|
+ textarea.style.top = areaPosition.y + 'px'
|
|
|
+ textarea.style.left = areaPosition.x + 'px'
|
|
|
+ textarea.style.background = 'transparent'
|
|
|
+ textarea.style.color = 'red'
|
|
|
+ textarea.style.fontSize = '16px'
|
|
|
+ textarea.style.borderColor = 'red'
|
|
|
+ textarea.style.boxShadow = 'none'
|
|
|
+ textarea.style.height = text.height() + 'px'
|
|
|
+ textarea.className = 'textarea'
|
|
|
+ textarea.style.width = text.width()
|
|
|
+
|
|
|
+ textarea.focus()
|
|
|
+ _this.isDltText = true //设置删除按键的状态,文本框状态应该是删除文字不能删除图形
|
|
|
+ text.hide()
|
|
|
+ _this.tr.hide()
|
|
|
+ textarea.addEventListener('input', () => {
|
|
|
+ textarea.style.height = 'auto'
|
|
|
+ textarea.style.height = textarea.scrollHeight + 'px'
|
|
|
+ _this.isDltText = true
|
|
|
+ })
|
|
|
+ textarea.addEventListener('blur', function (e) {
|
|
|
+ if (textarea.value) {
|
|
|
+ text.text(textarea.value)
|
|
|
+ text.width(textarea.clientWidth)
|
|
|
+ text.height(textarea.scrollHeight)
|
|
|
+ text.show()
|
|
|
+
|
|
|
+ _this.markLayer.draw()
|
|
|
+ } else {
|
|
|
+ text.remove()
|
|
|
+ }
|
|
|
+ _this.tr.nodes([])
|
|
|
+ _this.tr.show()
|
|
|
+ document.body.removeChild(textarea)
|
|
|
+ _this.isDltText = false
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ this.text.x(current.x)
|
|
|
+ this.text.y(current.y)
|
|
|
+ }
|
|
|
+ // this.text.zIndex(100)
|
|
|
+ this.tr.nodes([this.text])
|
|
|
+ this.markLayer.add(this.tr)
|
|
|
+ this.markLayer.add(this.text)
|
|
|
+ this.stage.add(this.markLayer)
|
|
|
+ },
|
|
|
+ drawLine(index) {
|
|
|
+ this.activeIcon = index
|
|
|
+ this.mouseStatus = 'line'
|
|
|
+ },
|
|
|
+ startLine(current) {
|
|
|
+ let _this = this
|
|
|
+ if (!this.line) {
|
|
|
+ this.line = new Konva.Line({
|
|
|
+ id: this.uuid(),
|
|
|
+ stroke: 'red',
|
|
|
+ strokeWidth: 3,
|
|
|
+ draggable: false,
|
|
|
+ tension: 1,
|
|
|
+ points: [_this.clickPoint.x / _this.scaleDefault, _this.clickPoint.y / _this.scaleDefault]
|
|
|
+ })
|
|
|
+ // 监听点击事件设置选中状态
|
|
|
+ this.line.on('click', (evt) => {
|
|
|
+ _this.resizeBefore = _this.mouseStatus == 'resize' ? _this.resizeBefore : _this.mouseStatus//记录resize之前的状态
|
|
|
+ _this.mouseStatus = 'resize'
|
|
|
+ evt.target.draggable(true)
|
|
|
+ evt.cancelBubble = true //阻止事件冒泡
|
|
|
+ _this.tr.nodes([evt.target])
|
|
|
+ _this.markLayer.add(_this.tr)
|
|
|
+ })
|
|
|
+ // 优化一些绘制逻辑
|
|
|
+ this.line.on('mouseout', (evt) => {
|
|
|
+ evt.cancelBubble = true //阻止事件冒泡
|
|
|
+ evt.target.draggable(false)
|
|
|
+ let nodes = _this.tr.nodes()
|
|
|
+ if (_this.mouseStatus == 'resize' && nodes.length == 0) _this.mouseStatus = _this.resizeBefore
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ this.line.points(this.line.points().concat([current.x / _this.scaleDefault, current.y / _this.scaleDefault]))
|
|
|
+ }
|
|
|
+ // this.line.zIndex(1)
|
|
|
+ this.markLayer.add(this.line)
|
|
|
+ this.stage.add(this.markLayer)
|
|
|
+ },
|
|
|
+ drawArrow(index) {
|
|
|
+ this.activeIcon = index
|
|
|
+ this.mouseStatus = 'arrow'
|
|
|
+ },
|
|
|
+ // 绘制箭头
|
|
|
+ startArrow(current) {
|
|
|
+ let _this = this
|
|
|
+ if (!this.arrow) {
|
|
|
+ this.arrow = new Konva.Arrow({
|
|
|
+ id: this.uuid(),
|
|
|
+ fill: 'transparent',
|
|
|
+ stroke: 'red',
|
|
|
+ strokeWidth: 4,
|
|
|
+ pointerLength: 10,
|
|
|
+ pointerWidth: 8,
|
|
|
+ draggable: false,
|
|
|
+ fill: 'red',
|
|
|
+ lineCap: 'round',
|
|
|
+ strokeScaleEnabled: false,
|
|
|
+ points: [_this.clickPoint.x / _this.scaleDefault, _this.clickPoint.y / _this.scaleDefault, (current.x) / _this.scaleDefault, (current.y) / _this.scaleDefault]
|
|
|
+ })
|
|
|
+ // 监听点击事件设置选中状态
|
|
|
+ this.arrow.on('click', (evt) => {
|
|
|
+ _this.resizeBefore = _this.mouseStatus == 'resize' ? _this.resizeBefore : _this.mouseStatus//记录resize之前的状态
|
|
|
+ _this.mouseStatus = 'resize'
|
|
|
+ evt.target.draggable(true)
|
|
|
+ evt.cancelBubble = true //阻止事件冒泡
|
|
|
+ _this.tr.nodes([evt.target])
|
|
|
+ _this.markLayer.add(_this.tr)
|
|
|
+ })
|
|
|
+ // 优化一些绘制逻辑
|
|
|
+ this.arrow.on('mouseout', (evt) => {
|
|
|
+ evt.cancelBubble = true //阻止事件冒泡
|
|
|
+ evt.target.draggable(false)
|
|
|
+ let nodes = _this.tr.nodes()
|
|
|
+ if (_this.mouseStatus == 'resize' && nodes.length == 0) _this.mouseStatus = _this.resizeBefore
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ this.arrow.points([_this.clickPoint.x / _this.scaleDefault, _this.clickPoint.y / _this.scaleDefault, (current.x) / _this.scaleDefault, (current.y) / _this.scaleDefault])
|
|
|
+ }
|
|
|
+ // this.arrow.zIndex(1)
|
|
|
+ this.markLayer.add(this.arrow)
|
|
|
+ this.stage.add(this.markLayer)
|
|
|
+ },
|
|
|
+ drawOval(index) {
|
|
|
+ this.activeIcon = index
|
|
|
+ this.mouseStatus = 'oval'
|
|
|
+ },
|
|
|
+ startOval(current) {
|
|
|
+ console.log('scale', this.scaleDefault)
|
|
|
+ console.log('point', this.clickPoint)
|
|
|
+ let _this = this
|
|
|
+ //判断rect是否初始化
|
|
|
+ let rx = (current.x - _this.clickPoint.x) / _this.scaleDefault * 0.5
|
|
|
+ let ry = (_this.clickPoint.y - current.y) / _this.scaleDefault * 0.5
|
|
|
+ if (!this.oval) {
|
|
|
+ this.oval = new Konva.Ellipse({
|
|
|
+ id: this.uuid(),
|
|
|
+ // x: _this.clickPoint.x / _this.scaleDefault,
|
|
|
+ // y: _this.clickPoint.y / _this.scaleDefault,
|
|
|
+ x: _this.clickPoint.x,
|
|
|
+ y: _this.clickPoint.y,
|
|
|
+ radiusX: rx > 0 ? rx : -rx,
|
|
|
+ radiusY: ry,
|
|
|
+ fill: 'transparent',
|
|
|
+ stroke: 'red',
|
|
|
+ strokeWidth: 2,
|
|
|
+ draggable: false,
|
|
|
+ rotation: rx > 0 ? 0 : 180,
|
|
|
+ strokeScaleEnabled: false
|
|
|
+ })
|
|
|
+ // 监听点击事件设置选中状态
|
|
|
+ this.oval.on('click', (evt) => {
|
|
|
+ _this.resizeBefore = _this.mouseStatus == 'resize' ? _this.resizeBefore : _this.mouseStatus//记录resize之前的状态
|
|
|
+ _this.mouseStatus = 'resize'
|
|
|
+ evt.target.draggable(true)
|
|
|
+ evt.cancelBubble = true //阻止事件冒泡
|
|
|
+ _this.tr.nodes([evt.target])
|
|
|
+ _this.markLayer.add(_this.tr)
|
|
|
+ })
|
|
|
+ // 优化一些绘制逻辑
|
|
|
+ this.oval.on('mouseout', (evt) => {
|
|
|
+ evt.cancelBubble = true //阻止事件冒泡
|
|
|
+ evt.target.draggable(false)
|
|
|
+ let nodes = _this.tr.nodes()
|
|
|
+ if (_this.mouseStatus == 'resize' && nodes.length == 0) _this.mouseStatus = _this.resizeBefore
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ this.oval.x(_this.clickPoint.x / _this.scaleDefault + rx)
|
|
|
+ this.oval.y(_this.clickPoint.y / _this.scaleDefault - ry)
|
|
|
+ this.oval.radiusX(rx > 0 ? rx : -rx)
|
|
|
+ this.oval.radiusY(ry)
|
|
|
+ this.oval.rotation(rx > 0 ? 0 : 180)
|
|
|
+ }
|
|
|
+ this.oval.zIndex(1)
|
|
|
+ this.markLayer.add(this.oval)
|
|
|
+ this.stage.add(this.markLayer)
|
|
|
+ },
|
|
|
+ drawIcon(index) {
|
|
|
+ this.activeIcon = index
|
|
|
+ },
|
|
|
+ review(index) {
|
|
|
+ this.activeIcon = index
|
|
|
+ },
|
|
|
+ cancelFull(index) {
|
|
|
+ this.activeIcon = index
|
|
|
+ },
|
|
|
+ //绘制矩形
|
|
|
+ drawRect(index) {
|
|
|
+ this.activeIcon = index
|
|
|
+ this.mouseStatus = 'rect'
|
|
|
+ },
|
|
|
+ startRect(current) {
|
|
|
+ let _this = this
|
|
|
+ //判断rect是否初始化
|
|
|
+ if (!this.rect) {
|
|
|
+ this.rect = new Konva.Rect({
|
|
|
+ id: this.uuid(),
|
|
|
+ x: _this.clickPoint.x / _this.scaleDefault,
|
|
|
+ y: _this.clickPoint.y / _this.scaleDefault,
|
|
|
+ width: (current.x - _this.clickPoint.x) / _this.scaleDefault,
|
|
|
+ height: (current.y - _this.clickPoint.y) / _this.scaleDefault,
|
|
|
+ fill: 'transparent',
|
|
|
+ stroke: 'red',
|
|
|
+ strokeWidth: 2,
|
|
|
+ draggable: false,
|
|
|
+ strokeScaleEnabled: false
|
|
|
+ })
|
|
|
+ // 监听点击事件设置选中状态
|
|
|
+ this.rect.on('click', (evt) => {
|
|
|
+ _this.resizeBefore = _this.mouseStatus == 'resize' ? _this.resizeBefore : _this.mouseStatus//记录resize之前的状态
|
|
|
+ _this.mouseStatus = 'resize'
|
|
|
+ evt.target.draggable(true)
|
|
|
+ evt.cancelBubble = true //阻止事件冒泡
|
|
|
+ //Transformer
|
|
|
+ _this.tr.nodes([evt.target])
|
|
|
+ _this.markLayer.add(_this.tr)
|
|
|
+ })
|
|
|
+ // 优化一些绘制逻辑
|
|
|
+ this.rect.on('mouseout', (evt) => {
|
|
|
+ evt.cancelBubble = true //阻止事件冒泡
|
|
|
+ evt.target.draggable(false)
|
|
|
+ let nodes = _this.tr.nodes()
|
|
|
+ if (_this.mouseStatus == 'resize' && nodes.length == 0) _this.mouseStatus = _this.resizeBefore
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ this.rect.x(_this.clickPoint.x / _this.scaleDefault)
|
|
|
+ this.rect.y(_this.clickPoint.y / _this.scaleDefault)
|
|
|
+ this.rect.width((current.x - _this.clickPoint.x) / _this.scaleDefault)
|
|
|
+ this.rect.height((current.y - _this.clickPoint.y) / _this.scaleDefault)
|
|
|
+ }
|
|
|
+ this.rect.zIndex(1)
|
|
|
+ this.markLayer.add(this.rect)
|
|
|
+ this.stage.add(this.markLayer)
|
|
|
+ },
|
|
|
+ //防抖函数
|
|
|
+ debounce(func, delay) {
|
|
|
+ return function () {
|
|
|
+ window.clearTimeout(window.timeout)
|
|
|
+ window.timeout = setTimeout(() => {
|
|
|
+ clearTimeout(window.timeout)
|
|
|
+ func.apply(this, arguments)
|
|
|
+ }, delay)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //还原比例
|
|
|
+ restore() {
|
|
|
+ this.scaleDefault = 1
|
|
|
+ this.myScale()
|
|
|
+ },
|
|
|
+ // 缩小
|
|
|
+ smaller() {
|
|
|
+ console.log(this.stage)
|
|
|
+ this.scaleDefault -= this.scaleStep
|
|
|
+ if (this.scaleDefault < this.minScale) {
|
|
|
+ this.scaleDefault += this.scaleStep
|
|
|
+ //函数防抖,优化重复提示
|
|
|
+ this.debounce(() => {
|
|
|
+ this.$Message.warning('已经缩小到最小比例')
|
|
|
+ }, 400)()
|
|
|
+ } else {
|
|
|
+ this.myScale()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //放大
|
|
|
+ larger() {
|
|
|
+ console.log(this.stage)
|
|
|
+ this.scaleDefault += this.scaleStep
|
|
|
+ if (this.scaleDefault > this.maxScale) {
|
|
|
+ this.scaleDefault -= this.scaleStep
|
|
|
+ //函数防抖,优化重复提示
|
|
|
+ this.debounce(() => {
|
|
|
+ this.$Message.warning('已经放大到最大比例')
|
|
|
+ }, 400)()
|
|
|
+ } else {
|
|
|
+ this.myScale()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ myScale() {
|
|
|
+ this.stage.children.forEach(item => {
|
|
|
+ item.scale({
|
|
|
+ x: this.scaleDefault,
|
|
|
+ y: this.scaleDefault
|
|
|
+ })
|
|
|
+ })
|
|
|
+ this.stage.width(this.imgWidth * this.scaleDefault)
|
|
|
+ this.stage.height(this.imgHeight * this.scaleDefault)
|
|
|
+ },
|
|
|
+ //绑定鼠标滚轮事件,操作缩放功能
|
|
|
+ bundleScoll() {
|
|
|
+ let stage = document.getElementById('container')
|
|
|
+ let _this = this
|
|
|
+ stage.addEventListener('mousewheel', function (e) {
|
|
|
+ if (e.preventDefault) {
|
|
|
+ e.preventDefault()
|
|
|
+ } else {
|
|
|
+ window.event.returnValue == false
|
|
|
+ }
|
|
|
+ _this.scrollFunc(e)
|
|
|
+ }, false) || stage.addEventListener('DOMMouseScroll', function (e) {
|
|
|
+ if (e.preventDefault) {
|
|
|
+ e.preventDefault()
|
|
|
+ } else {
|
|
|
+ window.event.returnValue == false
|
|
|
+ }
|
|
|
+ _this.scrollFunc(e)
|
|
|
+ }, false)
|
|
|
+ },
|
|
|
+ //判断鼠标放大还是缩小
|
|
|
+ scrollFunc(e) {
|
|
|
+ e = e || window.event
|
|
|
+ if (e.wheelDelta) { // 判断浏览器IE,谷歌滑轮事件
|
|
|
+ if (e.wheelDelta > 0) { // 当滑轮向上滚动时
|
|
|
+ this.larger()
|
|
|
+ }
|
|
|
+ if (e.wheelDelta < 0) { // 当滑轮向下滚动时
|
|
|
+ this.smaller()
|
|
|
+ }
|
|
|
+ } else if (e.detail) { // Firefox滑轮事件
|
|
|
+ if (e.detail > 0) { // 当滑轮向上滚动时
|
|
|
+ this.larger()
|
|
|
+ }
|
|
|
+ if (e.detail < 0) { // 当滑轮向下滚动时
|
|
|
+ this.smaller()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //获取在canvas上的坐标
|
|
|
+ getCanvasPoint(x, y) {
|
|
|
+ // let canvas = document.getElementById('container')
|
|
|
+ let canvas = document.getElementsByClassName('konvajs-content')
|
|
|
+ let cs = canvas.length ? canvas[0] : null
|
|
|
+ if (cs) {
|
|
|
+ let canvasRect = cs.getBoundingClientRect()
|
|
|
+ return {
|
|
|
+ x: x - canvasRect.left,
|
|
|
+ y: y - canvasRect.top
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return {
|
|
|
+ x, y
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+ //按下鼠标事件
|
|
|
+ canvasMouseDown(e) {
|
|
|
+ this.isMouseDown = true
|
|
|
+ this.clickPoint = this.getCanvasPoint(e.clientX, e.clientY)
|
|
|
+ },
|
|
|
+ //鼠标弹起事件
|
|
|
+ canvasMouseUp() {
|
|
|
+ this.isMouseDown = false
|
|
|
+ switch (this.mouseStatus) {
|
|
|
+ case 'move':
|
|
|
+ break
|
|
|
+ case 'rect':
|
|
|
+ this.rect = null
|
|
|
+ break
|
|
|
+ case 'oval':
|
|
|
+ this.oval = null
|
|
|
+ break
|
|
|
+ case 'arrow':
|
|
|
+ this.arrow = null
|
|
|
+ break
|
|
|
+ case 'text':
|
|
|
+ this.text = null
|
|
|
+ break
|
|
|
+ case 'line':
|
|
|
+ this.line = null
|
|
|
+ break
|
|
|
+ // case 'img':
|
|
|
+ // this.img = null
|
|
|
+ // break
|
|
|
+ default:
|
|
|
+ break
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //鼠标移动事件
|
|
|
+ canvasMouseMove(e) {
|
|
|
+ console.log(this.mouseStatus)
|
|
|
+ if (this.isMouseDown) {
|
|
|
+ let current = this.getCanvasPoint(e.clientX, e.clientY)
|
|
|
+ switch (this.mouseStatus) {
|
|
|
+ case 'move':
|
|
|
+ this.$refs["canvasScroll"].scrollBy({
|
|
|
+ dx: this.clickPoint.x - current.x,
|
|
|
+ dy: this.clickPoint.y - current.y
|
|
|
+ }, 0)
|
|
|
+ break
|
|
|
+ case 'rect':
|
|
|
+ this.startRect(current)
|
|
|
+ break
|
|
|
+ case 'oval':
|
|
|
+ this.startOval(current)
|
|
|
+ break
|
|
|
+ case 'arrow':
|
|
|
+ this.startArrow(current)
|
|
|
+ break
|
|
|
+ case 'text':
|
|
|
+ this.startText(current)
|
|
|
+ break
|
|
|
+ case 'line':
|
|
|
+ this.startLine(current)
|
|
|
+ break
|
|
|
+ default:
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ //清除所有批注
|
|
|
+ clear(index) {
|
|
|
+ this.activeIcon = index
|
|
|
+ this.markLayer.removeChildren()
|
|
|
+ this.stage.add(this.markLayer)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ let _this = this
|
|
|
+
|
|
|
+ //创建画布
|
|
|
+ _this.stage = new Konva.Stage({
|
|
|
+ container: 'container',
|
|
|
+ id: 'canvas',
|
|
|
+ width: 600,
|
|
|
+ height: 240
|
|
|
+ })
|
|
|
+ _this.orgLayer = new Konva.Layer()
|
|
|
+ _this.markLayer = new Konva.Layer()
|
|
|
+ _this.stage.add(_this.orgLayer)
|
|
|
+ _this.stage.add(_this.markLayer)
|
|
|
+ _this.orgLayer.batchDraw()
|
|
|
+ _this.bundleScoll()
|
|
|
+ _this.stage.on('click', (evt) => {
|
|
|
+ _this.tr.nodes([])
|
|
|
+ })
|
|
|
+ _this.stage.on('mouseover', (evt) => {
|
|
|
+ let nodes = _this.tr.nodes()
|
|
|
+ if (_this.mouseStatus == 'resize' && nodes.length == 0) _this.mouseStatus = _this.resizeBefore
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
+ this.tr = new Konva.Transformer({
|
|
|
+ rotateEnabled: false,
|
|
|
+ anchorStroke: 'red',
|
|
|
+ enabledAnchors: ['top-center', 'top-left', 'top-right', 'middle-left', 'middle-right', 'bottom-left', 'bottom-center', 'bottom-right'],
|
|
|
+ anchorSize: 8,
|
|
|
+ borderStroke: 'red'
|
|
|
+ })
|
|
|
+ this.tr.borderEnabled(true)
|
|
|
+ this.tr.anchorCornerRadius(10)
|
|
|
+
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ //监听删除按键,删除图形
|
|
|
+ document.onkeydown = e => {
|
|
|
+ if (e.keyCode == 8 && !this.isDltText) {
|
|
|
+ let shape = this.tr ? this.tr.nodes() : []
|
|
|
+ if (shape.length) {
|
|
|
+ shape[0].remove()
|
|
|
+ this.tr.nodes([])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ bgImg: {
|
|
|
+ handler(n, o) {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.orgLayer.removeChildren()
|
|
|
+ this.markLayer.removeChildren()
|
|
|
+ let imageObj = new Image()
|
|
|
+ let _this = this
|
|
|
+ imageObj.onload = function () {
|
|
|
+ //创建画布
|
|
|
+ _this.imgWidth = imageObj.width
|
|
|
+ _this.imgHeight = imageObj.height
|
|
|
+ _this.stage.width(imageObj.width)
|
|
|
+ _this.stage.height(imageObj.height)
|
|
|
+ let img = new Konva.Image({
|
|
|
+ x: 0,
|
|
|
+ y: 0,
|
|
|
+ image: imageObj,
|
|
|
+ width: imageObj.width,
|
|
|
+ height: imageObj.height
|
|
|
+ })
|
|
|
+ _this.orgLayer.add(img)
|
|
|
+ _this.orgLayer.batchDraw()
|
|
|
+ }
|
|
|
+ imageObj.src = this.bgImg
|
|
|
+ this.stage.add(this.orgLayer)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ immediate: true,
|
|
|
+ deep: true
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+<style scoped lang="less">
|
|
|
+.mark-stage {
|
|
|
+ flex: 1;
|
|
|
+ overflow: hidden;
|
|
|
+ background: white;
|
|
|
+ text-align: center;
|
|
|
+ position: relative;
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+.container-box {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ width: 100%;
|
|
|
+ padding: 10px;
|
|
|
+}
|
|
|
+</style>
|
|
|
+<style>
|
|
|
+.textarea:focus {
|
|
|
+ box-shadow: none;
|
|
|
+ overflow: hidden;
|
|
|
+ outline: none !important;
|
|
|
+ line-height: 1.5;
|
|
|
+}
|
|
|
+</style>
|