Paper.js的使用
安装Paper
npm install paper
引入Paper.js
import * as Paper from "paper" ;
创建画布
< template>
< canvas id= "myCanvas" ref= "myCanvas" > < / canvas>
< / template>
实例化Paper、Project以及Tool
const paperInstance = new Paper. PaperScope ( ) ;
let project : null | paper. Project = null ;
const tool = new Paper. Tool ( ) ;
onMounted ( ( ) => {
paperInstance. setup ( document. getElementById ( "myCanvas" ) as HTMLCanvasElement) ;
project = new Paper. Project (
document. getElementById ( "myCanvas" ) as HTMLCanvasElement
) ;
tool. activate ( ) ;
} ) ;
画圆
const drawCircle = ( ) => {
const circle = new Paper. Path. Circle ( {
center : [ 200 , 100 ] ,
radius : 50 ,
fillColor : new Paper. Color ( "red" ) ,
strokeColor : new Paper. Color ( "black" ) ,
} ) ;
circle. strokeWidth = 2 ;
} ;
画点和线
const drawPointAndLine = ( ) => {
const point = new Paper. Point ( 500 , 100 ) ;
const path = new Paper. Path ( ) ;
path. add ( point) ;
const copyPoint = point. clone ( ) ;
copyPoint. set ( 600 , 100 ) ;
path. add ( copyPoint) ;
path. strokeColor = new Paper. Color ( "black" ) ;
path. strokeWidth = 4 ;
path. selected = true ;
} ;
画矩形
const drawRectangle = ( ) => {
const rect1 = new Paper. Path. Rectangle ( {
center : [ 200 , 400 ] ,
size : [ 50 , 100 ] ,
radius : [ 5 , 5 ] ,
fillColor : "orange" ,
strokeColor : "black" ,
strokeWidth : 4 ,
rotation : 45 ,
selected : true ,
} ) ;
const topLeft = new Paper. Point ( 200 , 20 ) ;
const rectSize = new Paper. Size ( 200 , 200 ) ;
const rect2 = new Paper. Rectangle ( topLeft, rectSize) ;
const radius = new Paper. Size ( 30 , 30 ) ;
const path = new Paper. Path. Rectangle ( rect2, radius) ;
path. fillColor = new Paper. Color ( "blue" ) ;
path. position. set ( {
x : 300 ,
y : 300 ,
} ) ;
path. selected = true ;
} ;
导入图片
import Demo1 from "../../assets/demo1.jpg" ;
const drawImg = ( ) => {
const img = new Paper. Raster ( Demo1) ;
img. position. set ( 700 , 600 ) ;
img. scale ( 0.2 ) ;
} ;
画文字
const drawText = ( ) => {
const text = new Paper. PointText ( {
position : [ 500 , 200 ] ,
fillColor : "black" ,
justification : "center" ,
fontSize : 20 ,
content : "测试文字" ,
locked : false ,
} ) ;
} ;
Item组
const drawGroup = ( ) => {
const group = new Paper. Group ( ) ;
const text = new Paper. PointText ( {
position : [ 0 , - 50 - 10 ] ,
content : "圆" ,
fillColor : "black" ,
justification : "center" ,
fontSize : 20 ,
} ) ;
const circle = new Paper. Path. Circle ( {
center : [ 0 , 0 ] ,
radius : 50 ,
fillColor : "red" ,
} ) ;
group. addChildren ( [ text, circle] ) ;
group. position. set ( 1200 , 800 ) ;
} ;
曲线
const drawCurve = ( ) => {
const group = new Paper. Group ( ) ;
const earth = new Paper. Path. Circle ( {
center : [ 800 , 200 ] ,
radius : 50 ,
fillColor : new Paper. Color ( "green" ) ,
} ) ;
var firstPoint1 = calculatePointOnCircle ( 800 , 200 , 50 , ( Math. PI / 18 ) * 19 ) ;
var secondPoint1 = calculatePointOnCircle ( 800 , 200 , 50 , ( Math. PI / 18 ) * 1 ) ;
var handleOut1 = new Paper. Point ( 160 , 60 ) ;
var handleIn1 = new Paper. Point ( - 160 , 20 ) ;
var firstSegment = new Paper. Segment ( firstPoint1, undefined , handleIn1) ;
var secondSegment = new Paper. Segment ( secondPoint1, handleOut1, undefined ) ;
const curve1 = new Paper. Path ( [ firstSegment, secondSegment] ) ;
curve1. strokeColor = new Paper. Color ( "black" ) ;
curve1. strokeWidth = 8 ;
curve1. locked = true ;
curve1. selected = false ;
group. addChildren ( [ earth, curve1] ) ;
} ;
监听键盘事件
const onKeyDown = ( ) => {
tool. onKeyDown = ( event : any) => {
console. log ( event) ;
if ( event. event. key === "z" && event. event. ctrlKey) {
}
} ;
} ;
监听鼠标事件
const onMouse = ( ) => {
const children = project?. activeLayer. children;
tool. onMouseDown = ( event : any) => {
if ( ! event. item) {
children?. forEach ( ( item : any) => {
item. selected = false ;
} ) ;
} else {
children?. forEach ( ( item : any) => {
item. selected = false ;
} ) ;
event. item. selected = true ;
}
} ;
children?. forEach ( ( item : any) => {
item. onMouseDown = ( ) => {
project?. activeLayer. addChild ( item) ;
item. selected = true ;
} ;
item. onMouseDrag = ( event : paper. MouseEvent) => {
item. position. set (
item. position. x + event. delta. x,
item. position. y + event. delta. y
) ;
} ;
} ) ;
} ;
设置动画
let direction = "right" ;
const drawAnimate = ( ) => {
const node = new Paper. Path. Circle ( {
center : [ 200 , 100 ] ,
radius : 50 ,
} ) ;
node. strokeColor = new Paper. Color ( "black" ) ;
node. fillColor = new Paper. Color ( "white" ) ;
node. onFrame = ( ) => {
const maxWidth = document. body. clientWidth;
if ( direction === "right" ) {
if ( node. bounds. right >= maxWidth) {
direction = "left" ;
}
} else {
if ( node. bounds. left <= 0 ) {
direction = "right" ;
}
}
if ( direction === "right" ) {
node. bounds. x += 5 ;
} else {
node. bounds. x -= 5 ;
}
} ;
} ;
动画线
const drawAnimateLine = ( ) => {
const line = new Paper. Path. Line ( {
from : [ 1200 , 200 ] ,
to : [ 1200 , 600 ] ,
strokeColor : new Paper. Color ( "red" ) ,
strokeWidth : 8 ,
} ) ;
line. style. dashArray = [ 10 , 10 ] ;
line. onFrame = ( ) => {
line. style. dashOffset -= 1 ;
if ( line. style. dashOffset <= 0 ) {
line. style. dashOffset = 100 ;
}
} ;
} ;
下载成图片
const screenShot = ( ) => {
const flash = project?. exportSVG ( ) ;
var serializer = new XMLSerializer ( ) ;
var xmlString = serializer. serializeToString ( flash as SVGAElement) ;
var blob = new Blob ( [ xmlString] , { type : "image/svg+xml;charset=utf-8" } ) ;
var url = URL . createObjectURL ( blob) ;
var a = document. createElement ( "a" ) ;
a. href = url;
a. download = "my-svg-file.svg" ;
document. body. appendChild ( a) ;
a. click ( ) ;
document. body. removeChild ( a) ;
} ;
缩放画布
const mouseWheel = ( e : any) => {
paperInstance. view. zoom = paperInstance. view. zoom * ( 1 + e. wheelDelta / 1000 ) ;
} ;
onMounted ( ( ) => {
canvasEl. addEventListener ( "wheel" , mouseWheel) ;
} ) ;
onUnmounted ( ( ) => {
const canvasEl = document. getElementById ( "myCanvas" ) as HTMLCanvasElement;
canvasEl. removeEventListener ( "wheel" , mouseWheel) ;
} ) ;
拖拽画布
const downPoint = {
x : 0 ,
y : 0 ,
} ;
let zoom = 1 ;
const mouseMove = ( e : any) => {
const translateX = e. x - downPoint. x;
const translateY = e. y - downPoint. y;
paperInstance. view. translate ( {
x : translateX / zoom,
y : translateY / zoom,
} ) ;
downPoint. x = e. x;
downPoint. y = e. y;
} ;
const cancelMove = ( ) => {
const canvasEl = document. getElementById ( "myCanvas" ) as HTMLCanvasElement;
canvasEl. removeEventListener ( "mousemove" , mouseMove) ;
canvasEl. removeEventListener ( "mouseup" , cancelMove) ;
} ;
onMounted ( ( ) => {
paperInstance. view. onMouseDown = ( e : paper. MouseEvent) => {
const ele = e. target as unknown as paper. View;
if ( ele === paperInstance. view) {
downPoint. x = e. x;
downPoint. y = e. y;
zoom = paperInstance. view. zoom;
canvasEl. addEventListener ( "mousemove" , mouseMove) ;
canvasEl. addEventListener ( "mouseup" , cancelMove) ;
}
} ;
} ) ;
自定义选中样式和拖拽边角进行放大缩小
const addSelect = ( item : paper. Item) => {
const rect = new Paper. Path. Rectangle ( {
center : item. bounds. center,
size : item. bounds. size,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
} ) ;
const topLeftRect = new Paper. Path. Rectangle ( {
center : item. bounds. topLeft,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "topLeftRect" ,
} ) ;
const topRightRect = new Paper. Path. Rectangle ( {
center : item. bounds. topRight,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "topRightRect" ,
} ) ;
const bottomLeftRect = new Paper. Path. Rectangle ( {
center : item. bounds. bottomLeft,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "bottomLeftRect" ,
} ) ;
const bottomRightRect = new Paper. Path. Rectangle ( {
center : item. bounds. bottomRight,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "bottomRightRect" ,
} ) ;
const topCenterRect = new Paper. Path. Rectangle ( {
center : item. bounds. topCenter,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "topCenterRect" ,
} ) ;
const leftCenterRect = new Paper. Path. Rectangle ( {
center : item. bounds. leftCenter,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "leftCenterRect" ,
} ) ;
const rightCenterRect = new Paper. Path. Rectangle ( {
center : item. bounds. rightCenter,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "rightCenterRect" ,
} ) ;
const bottomCenterRect = new Paper. Path. Rectangle ( {
center : item. bounds. bottomCenter,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "bottomCenterRect" ,
} ) ;
const g1 = new Paper. Group ( [
rect,
topLeftRect,
topRightRect,
bottomLeftRect,
bottomRightRect,
topCenterRect,
leftCenterRect,
rightCenterRect,
bottomCenterRect,
] ) ;
const g2 = new Paper. Group ( [ item, g1] ) ;
if ( config. itemHandle?. includes ( "drag" ) ) {
g2. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
g2. position. set (
item. position. x + e. delta. x,
item. position. y + e. delta. y
) ;
} ;
}
topLeftRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if (
item. bounds. size. height - e. delta. y <= 20 ||
item. bounds. size. width - e. delta. x <= 20
) {
return ;
}
item. bounds. center. y += e. delta. y;
item. bounds. center. x += e. delta. x;
item. bounds. size. height -= e. delta. y;
item. bounds. size. width -= e. delta. x;
rect. bounds. center. y += e. delta. y;
rect. bounds. center. x += e. delta. x;
rect. bounds. size. height -= e. delta. y;
rect. bounds. size. width -= e. delta. x;
topLeftRect. bounds. x += e. delta. x;
topLeftRect. bounds. y += e. delta. y;
topRightRect. bounds. y += e. delta. y;
bottomLeftRect. bounds. x += e. delta. x;
topCenterRect. bounds. y += e. delta. y;
topCenterRect. bounds. x += e. delta. x / 2 ;
leftCenterRect. bounds. y += e. delta. y / 2 ;
leftCenterRect. bounds. x += e. delta. x;
rightCenterRect. bounds. y += e. delta. y / 2 ;
bottomCenterRect. bounds. x += e. delta. x / 2 ;
} ;
topRightRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if (
item. bounds. size. height - e. delta. y <= 20 ||
item. bounds. size. width + e. delta. x <= 20
) {
return ;
}
item. bounds. center. y += e. delta. y;
item. bounds. size. height -= e. delta. y;
item. bounds. size. width += e. delta. x;
rect. bounds. center. y += e. delta. y;
rect. bounds. size. height -= e. delta. y;
rect. bounds. size. width += e. delta. x;
topRightRect. bounds. x += e. delta. x;
topRightRect. bounds. y += e. delta. y;
topLeftRect. bounds. y += e. delta. y;
bottomRightRect. bounds. x += e. delta. x;
topCenterRect. bounds. y += e. delta. y;
topCenterRect. bounds. x += e. delta. x / 2 ;
leftCenterRect. bounds. y += e. delta. y / 2 ;
rightCenterRect. bounds. y += e. delta. y / 2 ;
rightCenterRect. bounds. x += e. delta. x;
bottomCenterRect. bounds. x += e. delta. x / 2 ;
} ;
bottomLeftRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if (
item. bounds. size. height + e. delta. y <= 20 ||
item. bounds. size. width - e. delta. x <= 20
) {
return ;
}
item. bounds. center. x += e. delta. x;
item. bounds. size. height += e. delta. y;
item. bounds. size. width -= e. delta. x;
rect. bounds. center. x += e. delta. x;
rect. bounds. size. height += e. delta. y;
rect. bounds. size. width -= e. delta. x;
bottomLeftRect. bounds. x += e. delta. x;
bottomLeftRect. bounds. y += e. delta. y;
topLeftRect. bounds. x += e. delta. x;
bottomRightRect. bounds. y += e. delta. y;
topCenterRect. bounds. x += e. delta. x / 2 ;
leftCenterRect. bounds. y += e. delta. y / 2 ;
leftCenterRect. bounds. x += e. delta. x;
rightCenterRect. bounds. y += e. delta. y / 2 ;
bottomCenterRect. bounds. y += e. delta. y;
bottomCenterRect. bounds. x += e. delta. x / 2 ;
} ;
bottomRightRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if (
item. bounds. size. height + e. delta. y <= 20 ||
item. bounds. size. width + e. delta. x <= 20
) {
return ;
}
item. bounds. size. height += e. delta. y;
item. bounds. size. width += e. delta. x;
rect. bounds. size. height += e. delta. y;
rect. bounds. size. width += e. delta. x;
bottomRightRect. bounds. x += e. delta. x;
bottomRightRect. bounds. y += e. delta. y;
topRightRect. bounds. x += e. delta. x;
bottomLeftRect. bounds. y += e. delta. y;
topCenterRect. bounds. x += e. delta. x / 2 ;
leftCenterRect. bounds. y += e. delta. y / 2 ;
rightCenterRect. bounds. y += e. delta. y / 2 ;
rightCenterRect. bounds. x += e. delta. x;
bottomCenterRect. bounds. y += e. delta. y;
bottomCenterRect. bounds. x += e. delta. x / 2 ;
} ;
topCenterRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if ( item. bounds. size. height - e. delta. y <= 20 ) {
return ;
}
item. bounds. center. y += e. delta. y;
item. bounds. size. height -= e. delta. y;
rect. bounds. center. y += e. delta. y;
rect. bounds. size. height -= e. delta. y;
topLeftRect. bounds. y += e. delta. y;
topRightRect. bounds. y += e. delta. y;
topCenterRect. bounds. y += e. delta. y;
leftCenterRect. bounds. y += e. delta. y / 2 ;
rightCenterRect. bounds. y += e. delta. y / 2 ;
} ;
leftCenterRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if ( item. bounds. size. width - e. delta. x <= 20 ) {
return ;
}
item. bounds. center. x += e. delta. x;
item. bounds. size. width -= e. delta. x;
rect. bounds. center. x += e. delta. x;
rect. bounds. size. width -= e. delta. x;
topLeftRect. bounds. x += e. delta. x;
bottomLeftRect. bounds. x += e. delta. x;
leftCenterRect. bounds. x += e. delta. x;
topCenterRect. bounds. x += e. delta. x / 2 ;
bottomCenterRect. bounds. x += e. delta. x / 2 ;
} ;
bottomCenterRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if ( item. bounds. size. height + e. delta. y <= 20 ) {
return ;
}
item. bounds. size. height += e. delta. y;
rect. bounds. size. height += e. delta. y;
bottomLeftRect. bounds. y += e. delta. y;
bottomRightRect. bounds. y += e. delta. y;
bottomCenterRect. bounds. y += e. delta. y;
leftCenterRect. bounds. y += e. delta. y / 2 ;
rightCenterRect. bounds. y += e. delta. y / 2 ;
} ;
rightCenterRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if ( item. bounds. size. width + e. delta. x <= 20 ) {
return ;
}
item. bounds. size. width += e. delta. x;
rect. bounds. size. width += e. delta. x;
topRightRect. bounds. x += e. delta. x;
bottomRightRect. bounds. x += e. delta. x;
rightCenterRect. bounds. x += e. delta. x;
topCenterRect. bounds. x += e. delta. x / 2 ;
bottomCenterRect. bounds. x += e. delta. x / 2 ;
} ;
[
topLeftRect,
topRightRect,
bottomLeftRect,
bottomRightRect,
topCenterRect,
leftCenterRect,
rightCenterRect,
bottomCenterRect,
] . forEach ( ( item ) => {
item. onMouseLeave = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
cursor. value = "default" ;
} ;
item. onMouseEnter = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
switch ( e. target. name) {
case "topLeftRect" :
cursor. value = "nw-resize" ;
break ;
case "topRightRect" :
cursor. value = "ne-resize" ;
break ;
case "bottomLeftRect" :
cursor. value = "sw-resize" ;
break ;
case "bottomRightRect" :
cursor. value = "se-resize" ;
break ;
case "topCenterRect" :
cursor. value = "n-resize" ;
break ;
case "leftCenterRect" :
cursor. value = "w-resize" ;
break ;
case "rightCenterRect" :
cursor. value = "e-resize" ;
break ;
case "bottomCenterRect" :
cursor. value = "s-resize" ;
break ;
}
} ;
} ) ;
return [ g1, g2, item] ;
} ;
完整代码
< template>
< div class = "container" >
< canvas id= "myCanvas" ref= "canvasEl" > < / canvas>
< / div>
< / template>
< script lang= "ts" >
export default { name : "Paper" } ;
< / script>
< script lang= "ts" setup>
import * as Paper from "paper" ;
import { onMounted, reactive } from "vue" ;
import Demo1 from "../../assets/demo1.jpg" ;
import { CanvasHandle, ItemHandle, usePaper } from "./" ;
let direction = "right" ;
const config = reactive ( {
zoom : true ,
canvasHandle : "select" as CanvasHandle,
itemHandle : [ "select" , "drag" ] as ItemHandle,
tooltips : ( ) => {
return "123" ;
} ,
} ) ;
const { canvasEl, cursor, registerMouseEvent } = usePaper ( config) ;
const drawAnimate = ( ) => {
const node = new Paper. Path. Circle ( {
center : [ 200 , 100 ] ,
radius : 50 ,
} ) ;
node. strokeColor = new Paper. Color ( "black" ) ;
node. fillColor = new Paper. Color ( "white" ) ;
node. onFrame = ( ) => {
const maxWidth = document. body. clientWidth;
if ( direction === "right" ) {
if ( node. bounds. right >= maxWidth) {
direction = "left" ;
}
} else {
if ( node. bounds. left <= 0 ) {
direction = "right" ;
}
}
if ( direction === "right" ) {
node. bounds. x += 5 ;
} else {
node. bounds. x -= 5 ;
}
} ;
} ;
const drawCircle = ( ) => {
const circle = new Paper. Path. Circle ( {
center : [ 200 , 100 ] ,
radius : 50 ,
fillColor : new Paper. Color ( "red" ) ,
strokeColor : new Paper. Color ( "black" ) ,
cursor : "pointer" ,
} ) ;
circle. strokeWidth = 2 ;
const pathData = "M 50 100 L 100 0 L 0 0 Z" ;
const path = new Paper. Path ( pathData) ;
path. strokeColor = new Paper. Color ( "black" ) ;
path. fillColor = new Paper. Color ( "green" ) ;
path. strokeWidth = 2 ;
path. strokeWidth = 2 ;
path. position. set ( 400 , 100 ) ;
} ;
const drawPointAndLine = ( ) => {
const point = new Paper. Point ( 500 , 100 ) ;
const path = new Paper. Path ( ) ;
path. add ( point) ;
const copyPoint = point. clone ( ) ;
copyPoint. set ( 600 , 100 ) ;
path. add ( copyPoint) ;
path. strokeColor = new Paper. Color ( "black" ) ;
path. strokeWidth = 4 ;
} ;
const drawRectangle = ( ) => {
const rect1 = new Paper. Path. Rectangle ( {
center : [ 200 , 400 ] ,
size : [ 50 , 100 ] ,
radius : [ 5 , 5 ] ,
fillColor : "orange" ,
strokeColor : "black" ,
strokeWidth : 4 ,
rotation : 45 ,
} ) ;
const topLeft = new Paper. Point ( 200 , 20 ) ;
const rectSize = new Paper. Size ( 200 , 200 ) ;
const rect2 = new Paper. Rectangle ( topLeft, rectSize) ;
const radius = new Paper. Size ( 30 , 30 ) ;
const path = new Paper. Path. Rectangle ( rect2, radius) ;
path. fillColor = new Paper. Color ( "blue" ) ;
path. position. set ( {
x : 300 ,
y : 300 ,
} ) ;
} ;
const drawImg = ( ) => {
const img = new Paper. Raster ( Demo1) ;
const rect2 = new Paper. Rectangle ( img. bounds. topLeft, img. bounds. size) ;
const path = new Paper. Path. Rectangle ( rect2) ;
path. strokeColor = new Paper. Color ( "transparent" ) ;
path. strokeWidth = 4 ;
img. position. set ( 700 , 600 ) ;
img. scale ( 0.2 ) ;
} ;
const drawText = ( ) => {
const text = new Paper. PointText ( {
position : [ 1600 , 50 ] ,
fillColor : "black" ,
justification : "center" ,
fontSize : 20 ,
content : "下载" ,
locked : false ,
name : "download" ,
style : {
cursor : "pointer" ,
} ,
} ) ;
} ;
const drawGroup = ( ) => {
const group = new Paper. Group ( ) ;
const text = new Paper. PointText ( {
position : [ 0 , - 50 - 10 ] ,
content : "圆" ,
fillColor : "black" ,
justification : "center" ,
fontSize : 20 ,
} ) ;
const circle = new Paper. Path. Circle ( {
center : [ 0 , 0 ] ,
radius : 50 ,
fillColor : "red" ,
} ) ;
group. addChildren ( [ text, circle] ) ;
group. position. set ( 1200 , 800 ) ;
} ;
const drawCurve = ( ) => {
const group = new Paper. Group ( ) ;
const earth = new Paper. Path. Circle ( {
center : [ 800 , 200 ] ,
radius : 50 ,
fillColor : new Paper. Color ( "green" ) ,
} ) ;
var firstPoint1 = calculatePointOnCircle ( 800 , 200 , 50 , ( Math. PI / 18 ) * 19 ) ;
var secondPoint1 = calculatePointOnCircle ( 800 , 200 , 50 , ( Math. PI / 18 ) * 1 ) ;
var handleOut1 = new Paper. Point ( 160 , 60 ) ;
var handleIn1 = new Paper. Point ( - 160 , 20 ) ;
var firstSegment = new Paper. Segment ( firstPoint1, undefined , handleIn1) ;
var secondSegment = new Paper. Segment ( secondPoint1, handleOut1, undefined ) ;
const curve1 = new Paper. Path ( [ firstSegment, secondSegment] ) ;
curve1. strokeColor = new Paper. Color ( "black" ) ;
curve1. strokeWidth = 8 ;
curve1. locked = true ;
curve1. selected = false ;
curve1. style. strokeCap = "round" ;
group. addChildren ( [ earth, curve1] ) ;
} ;
const drawAnimateLine = ( ) => {
const line = new Paper. Path. Line ( {
from : [ 1200 , 200 ] ,
to : [ 1200 , 600 ] ,
strokeColor : new Paper. Color ( "red" ) ,
strokeWidth : 8 ,
} ) ;
line. style. dashArray = [ 10 , 10 ] ;
line. onFrame = ( ) => {
line. style. dashOffset -= 1 ;
if ( line. style. dashOffset <= 0 ) {
line. style. dashOffset = 100 ;
}
} ;
} ;
const drawArc = ( ) => {
const group = new Paper. Group ( ) ;
const arc = new Paper. Path. Arc ( {
from : [ 0 , 50 ] ,
through : [ 50 , 0 ] ,
to : [ 50 , 100 ] ,
strokeColor : "black" ,
fillColor : "red" ,
strokeWidth : 4 ,
} ) ;
const pathData = "M 50 50 L 50 101 L -1 50 Z" ;
const path = new Paper. Path ( pathData) ;
path. fillColor = new Paper. Color ( "white" ) ;
path. strokeWidth = 0 ;
group. addChildren ( [ arc, path] ) ;
} ;
const calculatePointOnCircle = (
centerX : number,
centerY : number,
radius : number,
angle : number
) => {
var x = centerX + radius * Math. cos ( angle) ;
var y = centerY + radius * Math. sin ( angle) ;
return new Paper. Point ( x, y) ;
} ;
onMounted ( ( ) => {
drawCircle ( ) ;
drawPointAndLine ( ) ;
drawRectangle ( ) ;
drawImg ( ) ;
drawText ( ) ;
drawGroup ( ) ;
drawAnimateLine ( ) ;
drawAnimate ( ) ;
drawArc ( ) ;
setTimeout ( ( ) => {
drawCurve ( ) ;
registerMouseEvent ( ) ;
} , 3000 ) ;
} ) ;
< / script>
< style lang= "scss" scoped>
. container {
width : 100 % ;
height : 100 % ;
position : relative;
#myCanvas {
width : 100 % ;
height : 100 % ;
cursor : v- bind ( cursor) ;
}
. control {
div {
position : absolute;
width : 10px;
height : 10px;
background- color: #fff;
border : 1px solid blue;
}
. top- left {
cursor : nw- resize;
}
. top- right {
cursor : ne- resize;
}
. bottom- left {
cursor : sw- resize;
}
. bottom- right {
cursor : se- resize;
}
}
}
< / style>
将元素的拖拽缩放、canvas的拖拽缩放抽离成hook
import { nextTick, onMounted, onUnmounted, ref, toRaw, watch } from "vue" ;
import * as Paper from "paper" ;
export type CanvasHandle = "select" | "drag" | "none" ;
export type ItemHandle = CanvasHandle[ ] | CanvasHandle;
export interface PaperConfig {
zoom : boolean;
canvasHandle : CanvasHandle;
itemHandle : ItemHandle;
tooltips : string | ( ( ) => string) ;
}
export const usePaper = ( config : PaperConfig) => {
const defaultConfig : PaperConfig = {
zoom : true ,
canvasHandle : "drag" ,
itemHandle : "none" ,
tooltips : "我是提示" ,
} ;
config = { ... defaultConfig, ... config } ;
const paperInstance = ref< paper. PaperScope> ( new Paper. PaperScope ( ) ) ;
const canvasEl = ref< HTMLCanvasElement> ( ) ;
const zoom = ref ( 1 ) ;
const selection = ref< paper. Path. Rectangle> ( ) ;
const selectionGroup = ref< paper. Item[ ] > ( ) ;
const cursor = ref ( "default" ) ;
const downPoint = {
x : 0 ,
y : 0 ,
} ;
const map = new WeakMap ( ) ;
watch (
( ) => selectionGroup. value,
( newValue, oldValue ) => {
if ( oldValue) {
oldValue[ 0 ] . remove ( ) ;
}
}
) ;
const mouseWheel = ( e : any) => {
if ( config. zoom) {
e. preventDefault ( ) ;
paperInstance. value. view. zoom =
paperInstance. value. view. zoom * ( 1 + e. wheelDelta / 1000 ) ;
zoom. value = paperInstance. value. view. zoom;
}
} ;
const canvasHandleFn = ( ) => {
paperInstance. value. view. onMouseDown = ( event : paper. MouseEvent | any) => {
const ele = event. target as unknown as paper. View;
const view = toRaw ( paperInstance. value. view) ;
if ( config. canvasHandle === "drag" ) {
const mouseMove = ( e : any) => {
const translateX = e. x - downPoint. x;
const translateY = e. y - downPoint. y;
paperInstance. value. view. translate ( {
x : translateX / zoom. value,
y : translateY / zoom. value,
} ) ;
downPoint. x = e. x;
downPoint. y = e. y;
} ;
const cancelMove = ( ) => {
canvasEl. value?. removeEventListener ( "mousemove" , mouseMove) ;
canvasEl. value?. removeEventListener ( "mouseup" , cancelMove) ;
} ;
if ( ele === view) {
downPoint. x = event. event. pageX;
downPoint. y = event. event. pageY;
zoom. value = paperInstance. value. view. zoom;
canvasEl. value?. addEventListener ( "mousemove" , mouseMove) ;
canvasEl. value?. addEventListener ( "mouseup" , cancelMove) ;
}
}
if ( config. canvasHandle === "select" ) {
if ( ele === view) {
selection. value = new Paper. Path. Rectangle (
event. point,
new Paper. Size ( 1 , 1 )
) ;
selection. value. strokeWidth = 1 ;
selection. value. strokeColor = new Paper. Color ( 0 , 0 , 0 , 0.5 ) ;
selection. value. style. dashArray = [ 4 , 4 ] ;
selection. value. name = "selection" ;
}
if ( selectionGroup. value && ele === view) {
const children = selectionGroup. value[ 2 ] . removeChildren ( ) ;
children?. forEach ( ( item ) => {
item. addTo ( paperInstance. value. project) ;
} ) ;
selectionGroup. value = undefined ;
}
}
} ;
paperInstance. value. view. onMouseDrag = ( e : paper. MouseEvent) => {
if ( selection. value) {
selection. value. bounds. width += e. delta. x;
selection. value. bounds. height += e. delta. y;
}
} ;
paperInstance. value. view. onMouseUp = ( e : paper. MouseEvent) => {
if ( selection. value) {
let childrens : paper. Item[ ] = [ ] ;
const chooseItems = paperInstance. value. project. getItems ( {
match : ( item : paper. Item) => {
const { topLeft, bottomRight } = item. bounds;
if (
topLeft. x > selection. value! . bounds. topLeft. x &&
topLeft. y > selection. value! . bounds. topLeft. y &&
bottomRight. x < selection. value! . bounds. bottomRight. x &&
bottomRight. y < selection. value! . bounds. bottomRight. y
) {
if ( item instanceof Paper. Group ) {
childrens. push ( ... item. children) ;
return item;
} else {
if ( ! childrens. includes ( item) ) {
return item;
}
}
}
} ,
} ) ;
console. log ( chooseItems) ;
if ( chooseItems. length) {
const g = new Paper. Group ( [ ... chooseItems] ) ;
selectionGroup. value = addSelect ( g) ;
paperInstance. value. project?. activeLayer. addChild (
selectionGroup. value! [ 1 ]
) ;
}
if ( selection. value) {
selection. value! . remove ( ) ;
selection. value = undefined ;
}
downPoint. x = 0 ;
downPoint. y = 0 ;
}
} ;
} ;
const addSelect = ( item : paper. Item) => {
const rect = new Paper. Path. Rectangle ( {
center : item. bounds. center,
size : item. bounds. size,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
} ) ;
const topLeftRect = new Paper. Path. Rectangle ( {
center : item. bounds. topLeft,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "topLeftRect" ,
} ) ;
const topRightRect = new Paper. Path. Rectangle ( {
center : item. bounds. topRight,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "topRightRect" ,
} ) ;
const bottomLeftRect = new Paper. Path. Rectangle ( {
center : item. bounds. bottomLeft,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "bottomLeftRect" ,
} ) ;
const bottomRightRect = new Paper. Path. Rectangle ( {
center : item. bounds. bottomRight,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "bottomRightRect" ,
} ) ;
const topCenterRect = new Paper. Path. Rectangle ( {
center : item. bounds. topCenter,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "topCenterRect" ,
} ) ;
const leftCenterRect = new Paper. Path. Rectangle ( {
center : item. bounds. leftCenter,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "leftCenterRect" ,
} ) ;
const rightCenterRect = new Paper. Path. Rectangle ( {
center : item. bounds. rightCenter,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "rightCenterRect" ,
} ) ;
const bottomCenterRect = new Paper. Path. Rectangle ( {
center : item. bounds. bottomCenter,
size : [ 10 , 10 ] ,
fillColor : new Paper. Color ( "#fff" ) ,
strokeColor : new Paper. Color ( "blue" ) ,
strokeWidth : 1 ,
name : "bottomCenterRect" ,
} ) ;
const g1 = new Paper. Group ( [
rect,
topLeftRect,
topRightRect,
bottomLeftRect,
bottomRightRect,
topCenterRect,
leftCenterRect,
rightCenterRect,
bottomCenterRect,
] ) ;
const g2 = new Paper. Group ( [ item, g1] ) ;
if ( config. itemHandle?. includes ( "drag" ) ) {
g2. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
g2. position. set (
item. position. x + e. delta. x,
item. position. y + e. delta. y
) ;
} ;
}
topLeftRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if (
item. bounds. size. height - e. delta. y <= 20 ||
item. bounds. size. width - e. delta. x <= 20
) {
return ;
}
item. bounds. center. y += e. delta. y;
item. bounds. center. x += e. delta. x;
item. bounds. size. height -= e. delta. y;
item. bounds. size. width -= e. delta. x;
rect. bounds. center. y += e. delta. y;
rect. bounds. center. x += e. delta. x;
rect. bounds. size. height -= e. delta. y;
rect. bounds. size. width -= e. delta. x;
topLeftRect. bounds. x += e. delta. x;
topLeftRect. bounds. y += e. delta. y;
topRightRect. bounds. y += e. delta. y;
bottomLeftRect. bounds. x += e. delta. x;
topCenterRect. bounds. y += e. delta. y;
topCenterRect. bounds. x += e. delta. x / 2 ;
leftCenterRect. bounds. y += e. delta. y / 2 ;
leftCenterRect. bounds. x += e. delta. x;
rightCenterRect. bounds. y += e. delta. y / 2 ;
bottomCenterRect. bounds. x += e. delta. x / 2 ;
} ;
topRightRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if (
item. bounds. size. height - e. delta. y <= 20 ||
item. bounds. size. width + e. delta. x <= 20
) {
return ;
}
item. bounds. center. y += e. delta. y;
item. bounds. size. height -= e. delta. y;
item. bounds. size. width += e. delta. x;
rect. bounds. center. y += e. delta. y;
rect. bounds. size. height -= e. delta. y;
rect. bounds. size. width += e. delta. x;
topRightRect. bounds. x += e. delta. x;
topRightRect. bounds. y += e. delta. y;
topLeftRect. bounds. y += e. delta. y;
bottomRightRect. bounds. x += e. delta. x;
topCenterRect. bounds. y += e. delta. y;
topCenterRect. bounds. x += e. delta. x / 2 ;
leftCenterRect. bounds. y += e. delta. y / 2 ;
rightCenterRect. bounds. y += e. delta. y / 2 ;
rightCenterRect. bounds. x += e. delta. x;
bottomCenterRect. bounds. x += e. delta. x / 2 ;
} ;
bottomLeftRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if (
item. bounds. size. height + e. delta. y <= 20 ||
item. bounds. size. width - e. delta. x <= 20
) {
return ;
}
item. bounds. center. x += e. delta. x;
item. bounds. size. height += e. delta. y;
item. bounds. size. width -= e. delta. x;
rect. bounds. center. x += e. delta. x;
rect. bounds. size. height += e. delta. y;
rect. bounds. size. width -= e. delta. x;
bottomLeftRect. bounds. x += e. delta. x;
bottomLeftRect. bounds. y += e. delta. y;
topLeftRect. bounds. x += e. delta. x;
bottomRightRect. bounds. y += e. delta. y;
topCenterRect. bounds. x += e. delta. x / 2 ;
leftCenterRect. bounds. y += e. delta. y / 2 ;
leftCenterRect. bounds. x += e. delta. x;
rightCenterRect. bounds. y += e. delta. y / 2 ;
bottomCenterRect. bounds. y += e. delta. y;
bottomCenterRect. bounds. x += e. delta. x / 2 ;
} ;
bottomRightRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if (
item. bounds. size. height + e. delta. y <= 20 ||
item. bounds. size. width + e. delta. x <= 20
) {
return ;
}
item. bounds. size. height += e. delta. y;
item. bounds. size. width += e. delta. x;
rect. bounds. size. height += e. delta. y;
rect. bounds. size. width += e. delta. x;
bottomRightRect. bounds. x += e. delta. x;
bottomRightRect. bounds. y += e. delta. y;
topRightRect. bounds. x += e. delta. x;
bottomLeftRect. bounds. y += e. delta. y;
topCenterRect. bounds. x += e. delta. x / 2 ;
leftCenterRect. bounds. y += e. delta. y / 2 ;
rightCenterRect. bounds. y += e. delta. y / 2 ;
rightCenterRect. bounds. x += e. delta. x;
bottomCenterRect. bounds. y += e. delta. y;
bottomCenterRect. bounds. x += e. delta. x / 2 ;
} ;
topCenterRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if ( item. bounds. size. height - e. delta. y <= 20 ) {
return ;
}
item. bounds. center. y += e. delta. y;
item. bounds. size. height -= e. delta. y;
rect. bounds. center. y += e. delta. y;
rect. bounds. size. height -= e. delta. y;
topLeftRect. bounds. y += e. delta. y;
topRightRect. bounds. y += e. delta. y;
topCenterRect. bounds. y += e. delta. y;
leftCenterRect. bounds. y += e. delta. y / 2 ;
rightCenterRect. bounds. y += e. delta. y / 2 ;
} ;
leftCenterRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if ( item. bounds. size. width - e. delta. x <= 20 ) {
return ;
}
item. bounds. center. x += e. delta. x;
item. bounds. size. width -= e. delta. x;
rect. bounds. center. x += e. delta. x;
rect. bounds. size. width -= e. delta. x;
topLeftRect. bounds. x += e. delta. x;
bottomLeftRect. bounds. x += e. delta. x;
leftCenterRect. bounds. x += e. delta. x;
topCenterRect. bounds. x += e. delta. x / 2 ;
bottomCenterRect. bounds. x += e. delta. x / 2 ;
} ;
bottomCenterRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if ( item. bounds. size. height + e. delta. y <= 20 ) {
return ;
}
item. bounds. size. height += e. delta. y;
rect. bounds. size. height += e. delta. y;
bottomLeftRect. bounds. y += e. delta. y;
bottomRightRect. bounds. y += e. delta. y;
bottomCenterRect. bounds. y += e. delta. y;
leftCenterRect. bounds. y += e. delta. y / 2 ;
rightCenterRect. bounds. y += e. delta. y / 2 ;
} ;
rightCenterRect. onMouseDrag = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
if ( item. bounds. size. width + e. delta. x <= 20 ) {
return ;
}
item. bounds. size. width += e. delta. x;
rect. bounds. size. width += e. delta. x;
topRightRect. bounds. x += e. delta. x;
bottomRightRect. bounds. x += e. delta. x;
rightCenterRect. bounds. x += e. delta. x;
topCenterRect. bounds. x += e. delta. x / 2 ;
bottomCenterRect. bounds. x += e. delta. x / 2 ;
} ;
[
topLeftRect,
topRightRect,
bottomLeftRect,
bottomRightRect,
topCenterRect,
leftCenterRect,
rightCenterRect,
bottomCenterRect,
] . forEach ( ( item ) => {
item. onMouseLeave = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
cursor. value = "default" ;
} ;
item. onMouseEnter = ( e : paper. MouseEvent) => {
e. stopPropagation ( ) ;
switch ( e. target. name) {
case "topLeftRect" :
cursor. value = "nw-resize" ;
break ;
case "topRightRect" :
cursor. value = "ne-resize" ;
break ;
case "bottomLeftRect" :
cursor. value = "sw-resize" ;
break ;
case "bottomRightRect" :
cursor. value = "se-resize" ;
break ;
case "topCenterRect" :
cursor. value = "n-resize" ;
break ;
case "leftCenterRect" :
cursor. value = "w-resize" ;
break ;
case "rightCenterRect" :
cursor. value = "e-resize" ;
break ;
case "bottomCenterRect" :
cursor. value = "s-resize" ;
break ;
}
} ;
} ) ;
return [ g1, g2, item] ;
} ;
const registerMouseEvent = ( ) => {
const children = paperInstance. value. project. activeLayer. children;
children?. forEach ( ( item : any) => {
item. onMouseDown = ( event : paper. MouseEvent) => {
if ( config. itemHandle?. includes ( "select" ) ) {
if ( map. has ( event. target) ) {
selectionGroup. value = map. get ( event. target) ;
selectionGroup. value! [ 0 ] . remove ( ) ;
map. delete ( event. target) ;
selectionGroup. value = addSelect ( new Paper. Group ( event. target) ) ;
} else {
if ( selectionGroup. value) {
const current = selectionGroup. value[ 1 ] . getItems ( {
match : ( item : paper. Item) => {
if ( item === event. target) {
return item;
}
} ,
} ) ;
if ( ! current. length) {
selectionGroup. value = addSelect ( new Paper. Group ( event. target) ) ;
map. set ( event. target, selectionGroup. value) ;
}
} else {
selectionGroup. value = addSelect ( new Paper. Group ( event. target) ) ;
}
}
paperInstance. value. project. activeLayer. addChild (
selectionGroup. value! [ 1 ]
) ;
} else if (
config. itemHandle === "drag" ||
( config. itemHandle && config. itemHandle[ 0 ] === "drag" )
) {
paperInstance. value. project. activeLayer. addChild ( event. target) ;
}
} ;
item. onMouseDrag = ( event : paper. MouseEvent | any) => {
if (
config. itemHandle === "drag" ||
( config. itemHandle && config. itemHandle[ 0 ] === "drag" )
) {
item. position. set (
item. position. x + event. delta. x,
item. position. y + event. delta. y
) ;
}
let tootipsEl = document. querySelector ( ".tootips" ) as HTMLElement;
if ( ! tootipsEl) {
tootipsEl = document. createElement ( "div" ) ;
document. body. appendChild ( tootipsEl) ;
tootipsEl. innerHTML =
typeof config. tooltips === "string"
? config. tooltips
: config. tooltips ( ) ;
tootipsEl. className = "tootips" ;
tootipsEl. style. position = "absolute" ;
tootipsEl. style. left = event. event. offsetX + 10 + "px" ;
tootipsEl. style. top = event. event. offsetY + 10 + "px" ;
tootipsEl. style. color = "#999" ;
} else {
tootipsEl. style. display = "block" ;
tootipsEl. style. left = event. event. offsetX + 10 + "px" ;
tootipsEl. style. top = event. event. offsetY + 10 + "px" ;
}
} ;
item. onMouseEnter = ( e : paper. MouseEvent) => {
cursor. value = "pointer" ;
} ;
item. onMouseLeave = ( ) => {
cursor. value = "defatul" ;
let tootipsEl = document. querySelector ( ".tootips" ) as HTMLElement;
tootipsEl. style. display = "none" ;
} ;
item. onMouseMove = ( event : paper. MouseEvent | any) => {
let tootipsEl = document. querySelector ( ".tootips" ) as HTMLElement;
if ( ! tootipsEl) {
tootipsEl = document. createElement ( "div" ) ;
document. body. appendChild ( tootipsEl) ;
tootipsEl. innerHTML =
typeof config. tooltips === "string"
? config. tooltips
: config. tooltips ( ) ;
tootipsEl. className = "tootips" ;
tootipsEl. style. position = "absolute" ;
tootipsEl. style. left = event. event. offsetX + 10 + "px" ;
tootipsEl. style. top = event. event. offsetY + 10 + "px" ;
tootipsEl. style. color = "#999" ;
} else {
tootipsEl. style. display = "block" ;
tootipsEl. style. left = event. event. offsetX + 10 + "px" ;
tootipsEl. style. top = event. event. offsetY + 10 + "px" ;
}
} ;
} ) ;
} ;
onMounted ( ( ) => {
paperInstance. value. setup ( canvasEl. value! ) ;
canvasEl. value?. addEventListener ( "wheel" , mouseWheel) ;
nextTick ( ( ) => {
canvasHandleFn ( ) ;
registerMouseEvent ( ) ;
} ) ;
} ) ;
onUnmounted ( ( ) => {
paperInstance. value. project. clear ( ) ;
canvasEl. value?. removeEventListener ( "wheel" , mouseWheel) ;
} ) ;
return {
paperInstance,
canvasEl,
zoom,
cursor,
selectionGroup,
addSelect,
registerMouseEvent,
} ;
} ;