效果圖以下: css
github地址以下: github地址引入js和對應的css。真的有須要的小夥伴只要把我對應文件夾的dragger.js和dragger.css拷進本身的項目裏就能夠用啦,不限制前端框架啊,vue、react仍是html文件裏均可以使用哦html
import Drag from '../../static/dragger.js'
import './assets/css/dragger.css'
複製代碼
以後,實例化前端
new Drag({
id: 'box-dragger',
showAngle: true,
isScale: false,
showBorder: false
})
new Drag({
id: 'box-dragger2',
canZoom: false,
canRotate: false
})
new Drag({
id: 'img-box',
showAngle: true,
showPosition: true
})
new Drag({
id: 'test'
})
複製代碼
這兩種方式都實現過一次,第一種比較簡單,可是第一種,很差控制選中某個元素才讓操做點展現。vue
考慮如何讓用戶快速上手使用,可參考的點:react
字段 | 說明 | 是否必填 | 默認值 |
---|---|---|---|
id | 目標元素id | 是 | 無 |
container | 父容器id | 否 | body |
canRotate | 是否能夠旋轉 | 否 | true |
canZoom | 是否能夠縮放 | 否 | true |
canPull | 是否能夠拉昇 | 否 | true |
canMove | 是否能夠平移 | 否 | true |
showAngle | 展現角度 | 否 | false |
showPosition | 展現位置 | 否 | false |
isScale | 是否等比例縮放 | 否 | true |
showBorder | 是否展現pannel的border | 否 | false |
具體看圖: git
初始化參數github
初始化目標dom對象的位置:記錄其:bash
初始化pannel結構
當前的父容器中只有一個pannel結構,每次實例化對象時,會判斷一下若是當前這個父容器裏已經存在id爲pannel的結構,就將其子節點清空,按照當前實例化對象傳進來的屬性從新渲染pannel子結構。若是沒有id爲pannel的結構,就建立。前端框架
初始化事件app
initEvent () {
document.addEventListener('mousemove', e => {
e.preventDefault && e.preventDefault()
this.moveChange(e, this.targetObj)
})
document.addEventListener('mouseup', e => {
this.moveLeave(this.targetObj)
})
if (this.canMove) {
// 外層給this.pannelDom添加mousedown事件,是在全部實例化結束後,panneldom被展現在最後一個實例化對象上,鼠標按下它時,觸發moveInit事件
this.pannelDom.onmousedown = e => {
e.stopPropagation()
this.moveInit(9, e, this.targetObj)
}
this.targetObj.onmousedown = e => {
e.stopPropagation()
this.moveInit(9, e, this.targetObj)
this.initPannel()
// 在點擊其餘未被選中元素時,pannel定位到該元素上,重寫pannelDom事件,由於此時的this.pannelDom已經根據新的目標元素被重寫
this.pannelDom.onmousedown= e => {
this.moveInit(9, e, this.targetObj)
}
}
}
}
複製代碼
dom操做
this.mouseInit = {
x: Math.floor(e.clientX),
y: Math.floor(e.clientY)
}
this.preRadian = Math.atan2(this.mouseInit.y - this.centerPos.y, this.mouseInit.x - this.centerPos.x)
複製代碼
this.rotateCurrent = {
x: Math.floor(e.clientX),
y: Math.floor(e.clientY)
}
this.curRadian = Math.atan2(this.rotateCurrent.y - this.centerPos.y, this.rotateCurrent.x - this.centerPos.x)
複製代碼
this.tranformRadian = this.curRadian - this.preRadian
複製代碼
this.angle = this.getRotate(target) + Math.round(this.tranformRadian * 180 / Math.PI)
this.preRadian = this.curRadian //鼠標移動的每一下都計算這個角度,因此每一下移動前的弧度值都上一次移動後的弧度值
複製代碼
let disAngle = this.angle - this.initAngle
this.rightBottomPoint = this.getRotatedPoint(this.initRightBottomPoint, this.centerPos, disAngle)
this.rightTopPoint = this.getRotatedPoint(this.initRightTopPoint, this.centerPos, disAngle)
this.leftTopPoint = this.getRotatedPoint(this.initLeftTopPoint, this.centerPos, disAngle)
this.leftBottomPoint = this.getRotatedPoint(this.initLeftBottomPoint, this.centerPos, disAngle)
this.leftMiddlePoint = this.getRotatedPoint(this.initLeftMiddlePoint, this.centerPos, disAngle)
this.rightMiddlePoint = this.getRotatedPoint(this.initRightMiddlePoint, this.centerPos, disAngle)
this.topMiddlePoint = this.getRotatedPoint(this.initTopMiddlePoint, this.centerPos, disAngle)
this.bottomMiddlePoint = this.getRotatedPoint(this.initBottomMiddlePoint, this.centerPos, disAngle)
複製代碼
複製代碼
優化,mousemove事件添加節流函數
function throttle(fn, interval) {
let canRun = true;
return function () {
if (!canRun) return;
canRun = false;
setTimeout(() => {
fn.apply(this, arguments);
canRun = true;
}, interval);
};
}
let that = this
document.addEventListener('mousemove', throttle(function (e) {
e.preventDefault && e.preventDefault()
that.moveChange(e, that.targetObj)
}, 10))
複製代碼