Feat:新增触摸事件支持插件

This commit is contained in:
wanglin2 2023-06-12 14:14:55 +08:00
parent 5353888965
commit d69668a488
16 changed files with 283 additions and 7 deletions

View File

@ -60,6 +60,7 @@ class RichText {
padding: 0;
height: auto;
line-height: normal;
-webkit-user-select: text;
}
.ql-container {

View File

@ -0,0 +1,122 @@
// 手势事件支持类
class TouchEvent {
// 构造函数
constructor({ mindMap }) {
this.mindMap = mindMap
this.touchesNum = 0
this.singleTouchstartEvent = null
this.clickNum = 0
this.doubleTouchmoveDistance = 0
this.bindEvent()
}
// 绑定事件
bindEvent() {
this.onTouchstart = this.onTouchstart.bind(this)
this.onTouchmove = this.onTouchmove.bind(this)
this.onTouchcancel = this.onTouchcancel.bind(this)
this.onTouchend = this.onTouchend.bind(this)
window.addEventListener('touchstart', this.onTouchstart)
window.addEventListener('touchmove', this.onTouchmove)
window.addEventListener('touchcancel', this.onTouchcancel)
window.addEventListener('touchend', this.onTouchend)
}
// 解绑事件
unBindEvent() {
window.removeEventListener('touchstart', this.onTouchstart)
window.removeEventListener('touchmove', this.onTouchmove)
window.removeEventListener('touchcancel', this.onTouchcancel)
window.removeEventListener('touchend', this.onTouchend)
}
// 手指按下事件
onTouchstart(e) {
this.touchesNum = e.touches.length
if (this.touchesNum === 1) {
let touch = e.touches[0]
this.singleTouchstartEvent = touch
this.dispatchMouseEvent('mousedown', touch.target, touch)
}
}
// 手指移动事件
onTouchmove(e) {
let len = e.touches.length
if (len === 1) {
let touch = e.touches[0]
this.dispatchMouseEvent('mousemove', touch.target, touch)
} else if (len === 2) {
let touch1 = e.touches[0]
let touch2 = e.touches[1]
let distance = Math.sqrt(
Math.pow(touch1.clientX - touch2.clientX, 2) +
Math.pow(touch1.clientY - touch2.clientY, 2)
)
if (distance > this.doubleTouchmoveDistance) {
// 放大
this.mindMap.view.enlarge()
} else {
// 缩小
this.mindMap.view.narrow()
}
this.doubleTouchmoveDistance = distance
}
}
// 手指取消事件
onTouchcancel(e) {}
// 手指松开事件
onTouchend(e) {
this.dispatchMouseEvent('mouseup', e.target)
if (this.touchesNum === 1) {
// 模拟双击事件
this.clickNum++
setTimeout(() => {
this.clickNum = 0
}, 300)
let ev = this.singleTouchstartEvent
if (this.clickNum > 1) {
this.clickNum = 0
this.dispatchMouseEvent('dblclick', ev.target, ev)
} else {
this.dispatchMouseEvent('click', ev.target, ev)
}
}
this.touchesNum = 0
this.singleTouchstartEvent = null
this.doubleTouchmoveDistance = 0
}
// 发送鼠标事件
dispatchMouseEvent(eventName, target, e) {
let opt = {}
if (e) {
opt = {
screenX: e.screenX,
screenY: e.screenY,
clientX: e.clientX,
clientY: e.clientY,
which: 1
}
}
let event = new MouseEvent(eventName, {
view: window,
bubbles: true,
cancelable: true,
...opt
})
target.dispatchEvent(event)
}
// 插件被移除前做的事情
beforePluginRemove() {
this.unBindEvent()
}
}
TouchEvent.instanceName = 'touchEvent'
export default TouchEvent

55
web/package-lock.json generated
View File

@ -33,6 +33,7 @@
"markdown-it": "^13.0.1",
"markdown-it-checkbox": "^1.1.0",
"prettier": "^1.19.1",
"vconsole": "^3.15.1",
"vue-template-compiler": "^2.6.11",
"webpack": "^4.44.2"
}
@ -5168,6 +5169,18 @@
"node": ">=0.10.0"
}
},
"node_modules/copy-text-to-clipboard": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.1.0.tgz",
"integrity": "sha512-PFM6BnjLnOON/lB3ta/Jg7Ywsv+l9kQGD4TWDCSlRBGmqnnTM5MrDkhAFgw+8HZt0wW6Q2BBE4cmy9sq+s9Qng==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/copy-webpack-plugin": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.1.2.tgz",
@ -10351,6 +10364,12 @@
"integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==",
"dev": true
},
"node_modules/mutation-observer": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/mutation-observer/-/mutation-observer-1.0.3.tgz",
"integrity": "sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA==",
"dev": true
},
"node_modules/mute-stream": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
@ -15185,6 +15204,18 @@
"node": ">= 0.8"
}
},
"node_modules/vconsole": {
"version": "3.15.1",
"resolved": "https://registry.npmjs.org/vconsole/-/vconsole-3.15.1.tgz",
"integrity": "sha512-KH8XLdrq9T5YHJO/ixrjivHfmF2PC2CdVoK6RWZB4yftMykYIaXY1mxZYAic70vADM54kpMQF+dYmvl5NRNy1g==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.17.2",
"copy-text-to-clipboard": "^3.0.1",
"core-js": "^3.11.0",
"mutation-observer": "^1.0.3"
}
},
"node_modules/vendors": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz",
@ -20525,6 +20556,12 @@
"integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==",
"dev": true
},
"copy-text-to-clipboard": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.1.0.tgz",
"integrity": "sha512-PFM6BnjLnOON/lB3ta/Jg7Ywsv+l9kQGD4TWDCSlRBGmqnnTM5MrDkhAFgw+8HZt0wW6Q2BBE4cmy9sq+s9Qng==",
"dev": true
},
"copy-webpack-plugin": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.1.2.tgz",
@ -24567,6 +24604,12 @@
"integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==",
"dev": true
},
"mutation-observer": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/mutation-observer/-/mutation-observer-1.0.3.tgz",
"integrity": "sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA==",
"dev": true
},
"mute-stream": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
@ -28566,6 +28609,18 @@
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
"dev": true
},
"vconsole": {
"version": "3.15.1",
"resolved": "https://registry.npmjs.org/vconsole/-/vconsole-3.15.1.tgz",
"integrity": "sha512-KH8XLdrq9T5YHJO/ixrjivHfmF2PC2CdVoK6RWZB4yftMykYIaXY1mxZYAic70vADM54kpMQF+dYmvl5NRNy1g==",
"dev": true,
"requires": {
"@babel/runtime": "^7.17.2",
"copy-text-to-clipboard": "^3.0.1",
"core-js": "^3.11.0",
"mutation-observer": "^1.0.3"
}
},
"vendors": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz",

View File

@ -37,6 +37,7 @@
"markdown-it": "^13.0.1",
"markdown-it-checkbox": "^1.1.0",
"prettier": "^1.19.1",
"vconsole": "^3.15.1",
"vue-template-compiler": "^2.6.11",
"webpack": "^4.44.2"
},

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0">
<link rel="icon" href="./dist/logo.png">
<title>一个简单的web思维导图实现</title>
</head>

View File

@ -8,6 +8,8 @@ import '@/assets/icon-font/iconfont.css'
import 'viewerjs/dist/viewer.css'
import VueViewer from 'v-viewer'
import i18n from './i18n'
// import VConsole from 'vconsole'
// const vConsole = new VConsole()
Vue.config.productionTip = false
Vue.prototype.$bus = new Vue()

View File

@ -30,6 +30,7 @@ let APIList = [
'miniMap',
'watermark',
'associativeLine',
'touchEvent',
'xmind',
'markdown',
'utils'

View File

@ -4,7 +4,7 @@
Breaking change: Adjusted the directory structure of the simple-mind-map source code, Main impact: 1. The introduction path of the plugin needs to be modified. The constant file path needs to be modified.
New: 1.Supports one click zoom to fit the canvas function. 2.Press and hold the Ctrl key to activate the multi selection function on demand through configuration. 3.Support setting to left click to select multiple nodes and right click to drag the canvas. 4. Support controlling whether nodes are allowed to be edited. 5.Add a method for destroying mind maps.
New: 1.Supports one click zoom to fit the canvas function. 2.Press and hold the Ctrl key to activate the multi selection function on demand through configuration. 3.Support setting to left click to select multiple nodes and right click to drag the canvas. 4. Support controlling whether nodes are allowed to be edited. 5.Add a method for destroying mind maps. 6.Added touch event support plugin.
Fix: 1.Fix the issue where holding down the Ctrl key to select multiple nodes does not trigger the click event for the node. 2.Fixed the issue of node style loss when clearing a node and then entering text.

View File

@ -3,7 +3,7 @@
<h1>Changelog</h1>
<h2>0.6.0</h2>
<p>Breaking change: Adjusted the directory structure of the simple-mind-map source code, Main impact: 1. The introduction path of the plugin needs to be modified. The constant file path needs to be modified.</p>
<p>New: 1.Supports one click zoom to fit the canvas function. 2.Press and hold the Ctrl key to activate the multi selection function on demand through configuration. 3.Support setting to left click to select multiple nodes and right click to drag the canvas. 4. Support controlling whether nodes are allowed to be edited. 5.Add a method for destroying mind maps.</p>
<p>New: 1.Supports one click zoom to fit the canvas function. 2.Press and hold the Ctrl key to activate the multi selection function on demand through configuration. 3.Support setting to left click to select multiple nodes and right click to drag the canvas. 4. Support controlling whether nodes are allowed to be edited. 5.Add a method for destroying mind maps. 6.Added touch event support plugin.</p>
<p>Fix: 1.Fix the issue where holding down the Ctrl key to select multiple nodes does not trigger the click event for the node. 2.Fixed the issue of node style loss when clearing a node and then entering text.</p>
<h2>0.5.11</h2>
<p>New: Supports associative text editing.</p>

View File

@ -0,0 +1,18 @@
# TouchEvent plugin
> v0.6.0+
This plugin supports mobile touch events for users. The principle is to listen for 'touchstart', 'touchmove', and 'touchend' events on the mobile end, and then dispatch corresponding mouse events.
Currently, it supports single finger touch to move the canvas, click to activate nodes, double finger zoom the canvas, single finger double-click to reset and edit nodes.
## Register
```js
import MindMap from 'simple-mind-map'
import TouchEvent from 'simple-mind-map/src/plugins/TouchEvent.js'
MindMap.usePlugin(TouchEvent)
```
After registration and instantiation of `MindMap`, the instance can be obtained through `mindMap.touchEvent`.

View File

@ -0,0 +1,28 @@
<template>
<div>
<h1>TouchEvent plugin</h1>
<blockquote>
<p>v0.6.0+</p>
</blockquote>
<p>This plugin supports mobile touch events for users. The principle is to listen for 'touchstart', 'touchmove', and 'touchend' events on the mobile end, and then dispatch corresponding mouse events.</p>
<p>Currently, it supports single finger touch to move the canvas, click to activate nodes, double finger zoom the canvas, single finger double-click to reset and edit nodes.</p>
<h2>Register</h2>
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map&#x27;</span>
<span class="hljs-keyword">import</span> TouchEvent <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map/src/plugins/TouchEvent.js&#x27;</span>
MindMap.usePlugin(TouchEvent)
</code></pre>
<p>After registration and instantiation of <code>MindMap</code>, the instance can be obtained through <code>mindMap.touchEvent</code>.</p>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>

View File

@ -44,7 +44,8 @@ export default [
{ path: 'watermark', title: 'Watermark插件' },
{ path: 'xmind', title: 'XMind解析' },
{ path: 'deploy', title: '部署' },
{ path: 'client', title: '客户端' }
{ path: 'client', title: '客户端' },
{ path: 'touchEvent', title: 'TouchEvent插件' }
]
},
{
@ -72,7 +73,8 @@ export default [
{ path: 'view', title: 'View instance' },
{ path: 'watermark', title: 'Watermark plugin' },
{ path: 'xmind', title: 'XMind parse' },
{ path: 'deploy', title: 'Deploy' }
{ path: 'deploy', title: 'Deploy' },
{ path: 'touchEvent', title: 'TouchEvent plugin' }
]
}
]

View File

@ -4,7 +4,7 @@
破坏性更新调整了simple-mind-map源码的目录结构主要影响1.插件的引入路径需要修改。2.constant文件路径需要修改。
新增1.支持一键缩放至适应画布功能。 2.按住Ctrl键多选功能可通过配置按需开启。 3.支持设置为左键多选节点,右键拖动画布。 4.支持控制节点是否允许编辑。 5.新增销毁思维导图的方法。
新增1.支持一键缩放至适应画布功能。 2.按住Ctrl键多选功能可通过配置按需开启。 3.支持设置为左键多选节点,右键拖动画布。 4.支持控制节点是否允许编辑。 5.新增销毁思维导图的方法。 6.新增触摸事件支持插件。
修复1.修复按住ctrl键多选节点时不会触发节点的click事件的问题。 2.修复清空一个节点后再输入文字时节点样式丢失的问题。

View File

@ -3,7 +3,7 @@
<h1>Changelog</h1>
<h2>0.6.0</h2>
<p>破坏性更新调整了simple-mind-map源码的目录结构主要影响1.插件的引入路径需要修改2.constant文件路径需要修改</p>
<p>新增1.支持一键缩放至适应画布功能 2.按住Ctrl键多选功能可通过配置按需开启 3.支持设置为左键多选节点右键拖动画布 4.支持控制节点是否允许编辑 5.新增销毁思维导图的方法</p>
<p>新增1.支持一键缩放至适应画布功能 2.按住Ctrl键多选功能可通过配置按需开启 3.支持设置为左键多选节点右键拖动画布 4.支持控制节点是否允许编辑 5.新增销毁思维导图的方法 6.新增触摸事件支持插件</p>
<p>修复1.修复按住ctrl键多选节点时不会触发节点的click事件的问题 2.修复清空一个节点后再输入文字时节点样式丢失的问题</p>
<h2>0.5.11</h2>
<p>新增支持关联性文本编辑</p>

View File

@ -0,0 +1,18 @@
# TouchEvent插件
> v0.6.0+
该插件用户支持移动端触摸事件。原理是监听移动端的`touchstart``touchmove``touchend`事件,然后派发对应的鼠标事件。
目前支持单指触摸移动画布、点击激活节点,双指缩放画布,单指双击复位和编辑节点。
## 注册
```js
import MindMap from 'simple-mind-map'
import TouchEvent from 'simple-mind-map/src/plugins/TouchEvent.js'
MindMap.usePlugin(TouchEvent)
```
注册完且实例化`MindMap`后可通过`mindMap.touchEvent`获取到该实例。

View File

@ -0,0 +1,28 @@
<template>
<div>
<h1>TouchEvent插件</h1>
<blockquote>
<p>v0.6.0+</p>
</blockquote>
<p>该插件用户支持移动端触摸事件原理是监听移动端的<code>touchstart</code><code>touchmove</code><code>touchend</code>事件然后派发对应的鼠标事件</p>
<p>目前支持单指触摸移动画布点击激活节点双指缩放画布单指双击复位和编辑节点</p>
<h2>注册</h2>
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map&#x27;</span>
<span class="hljs-keyword">import</span> TouchEvent <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map/src/plugins/TouchEvent.js&#x27;</span>
MindMap.usePlugin(TouchEvent)
</code></pre>
<p>注册完且实例化<code>MindMap</code>后可通过<code>mindMap.touchEvent</code>获取到该实例</p>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>