@leafer-in/viewport 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,357 @@
1
+ this.LeaferIN = this.LeaferIN || {};
2
+ this.LeaferIN.viewport = (function (exports, core) {
3
+ 'use strict';
4
+
5
+ function addViewport(leafer, mergeConfig, custom) {
6
+ addViewportConfig(leafer.parentApp ? leafer.parentApp : leafer, mergeConfig);
7
+ if (leafer.isApp || custom)
8
+ return;
9
+ leafer.__eventIds.push(leafer.on_(core.MoveEvent.BEFORE_MOVE, (e) => {
10
+ leafer.zoomLayer.move(leafer.getValidMove(e.moveX, e.moveY));
11
+ }), leafer.on_(core.ZoomEvent.BEFORE_ZOOM, (e) => {
12
+ const { zoomLayer } = leafer;
13
+ const changeScale = leafer.getValidScale(e.scale);
14
+ if (changeScale !== 1) {
15
+ core.PointHelper.scaleOf(zoomLayer, e, changeScale);
16
+ zoomLayer.scale = zoomLayer.__.scaleX * changeScale;
17
+ }
18
+ }));
19
+ }
20
+ function addViewportConfig(leafer, mergeConfig) {
21
+ if (mergeConfig)
22
+ core.DataHelper.assign(leafer.config, mergeConfig);
23
+ core.DataHelper.assign(leafer.config, {
24
+ wheel: { preventDefault: true },
25
+ touch: { preventDefault: true },
26
+ pointer: { preventDefaultMenu: true }
27
+ }, leafer.userConfig);
28
+ }
29
+
30
+ function custom(leafer) {
31
+ addViewport(leafer, null, true);
32
+ }
33
+
34
+ function design(leafer) {
35
+ addViewport(leafer, {
36
+ zoom: {
37
+ min: 0.01,
38
+ max: 256
39
+ },
40
+ move: {
41
+ holdSpaceKey: true,
42
+ holdMiddleKey: true,
43
+ }
44
+ });
45
+ }
46
+
47
+ function document(leafer) {
48
+ addViewport(leafer, {
49
+ zoom: { min: 1 },
50
+ move: { scroll: 'limit' }
51
+ });
52
+ }
53
+
54
+ const debug = core.Debug.get('LeaferTypeCreator');
55
+ const LeaferTypeCreator = {
56
+ list: {},
57
+ register(name, fn) {
58
+ list[name] && debug.repeat(name);
59
+ list[name] = fn;
60
+ },
61
+ run(name, leafer) {
62
+ const fn = list[name];
63
+ fn && fn(leafer);
64
+ }
65
+ };
66
+ const { list, register } = LeaferTypeCreator;
67
+ register('viewport', addViewport);
68
+ register('custom', custom);
69
+ register('design', design);
70
+ register('document', document);
71
+
72
+ const MultiTouchHelper = {
73
+ getData(list) {
74
+ const a = list[0], b = list[1];
75
+ const lastCenter = core.PointHelper.getCenter(a.from, b.from);
76
+ const center = core.PointHelper.getCenter(a.to, b.to);
77
+ const move = { x: center.x - lastCenter.x, y: center.y - lastCenter.y };
78
+ const lastDistance = core.PointHelper.getDistance(a.from, b.from);
79
+ const distance = core.PointHelper.getDistance(a.to, b.to);
80
+ const scale = distance / lastDistance;
81
+ const rotation = core.PointHelper.getRotation(a.from, b.from, a.to, b.to);
82
+ return { move, scale, rotation, center };
83
+ }
84
+ };
85
+
86
+ const WheelEventHelper = {
87
+ getMove(event, config) {
88
+ let { moveSpeed } = config;
89
+ let { deltaX, deltaY } = event;
90
+ if (event.shiftKey && !deltaX) {
91
+ deltaX = deltaY;
92
+ deltaY = 0;
93
+ }
94
+ if (deltaX > 50)
95
+ deltaX = Math.max(50, deltaX / 3);
96
+ if (deltaY > 50)
97
+ deltaY = Math.max(50, deltaY / 3);
98
+ return { x: -deltaX * moveSpeed * 2, y: -deltaY * moveSpeed * 2 };
99
+ },
100
+ getScale(event, config) {
101
+ let zoom;
102
+ let scale = 1;
103
+ let { zoomMode, zoomSpeed } = config;
104
+ const delta = event.deltaY || event.deltaX;
105
+ if (zoomMode) {
106
+ zoom = (zoomMode === 'mouse') ? true : (!event.deltaX && (core.Platform.intWheelDeltaY ? Math.abs(delta) > 17 : Math.ceil(delta) !== delta));
107
+ if (event.shiftKey || event.metaKey || event.ctrlKey)
108
+ zoom = true;
109
+ }
110
+ else {
111
+ zoom = !event.shiftKey && (event.metaKey || event.ctrlKey);
112
+ }
113
+ if (zoom) {
114
+ zoomSpeed = core.MathHelper.within(zoomSpeed, 0, 1);
115
+ const min = event.deltaY ? config.delta.y : config.delta.x;
116
+ scale = 1 - delta / (min * 4) * zoomSpeed;
117
+ if (scale < 0.5)
118
+ scale = 0.5;
119
+ if (scale >= 1.5)
120
+ scale = 1.5;
121
+ }
122
+ return scale;
123
+ }
124
+ };
125
+
126
+ class Transformer {
127
+ get transforming() { return !!(this.moveData || this.zoomData || this.rotateData); }
128
+ constructor(interaction) {
129
+ this.interaction = interaction;
130
+ }
131
+ move(data) {
132
+ const { interaction } = this;
133
+ if (!data.moveType)
134
+ data.moveType = 'move';
135
+ if (!this.moveData) {
136
+ this.setPath(data);
137
+ this.moveData = Object.assign(Object.assign({}, data), { moveX: 0, moveY: 0 });
138
+ interaction.emit(core.MoveEvent.START, this.moveData);
139
+ }
140
+ data.path = this.moveData.path;
141
+ interaction.emit(core.MoveEvent.BEFORE_MOVE, data);
142
+ interaction.emit(core.MoveEvent.MOVE, data);
143
+ this.transformEndWait();
144
+ }
145
+ zoom(data) {
146
+ const { interaction } = this;
147
+ if (!this.zoomData) {
148
+ this.setPath(data);
149
+ this.zoomData = Object.assign(Object.assign({}, data), { scale: 1 });
150
+ interaction.emit(core.ZoomEvent.START, this.zoomData);
151
+ }
152
+ data.path = this.zoomData.path;
153
+ interaction.emit(core.ZoomEvent.BEFORE_ZOOM, data);
154
+ interaction.emit(core.ZoomEvent.ZOOM, data);
155
+ this.transformEndWait();
156
+ }
157
+ rotate(data) {
158
+ const { interaction } = this;
159
+ if (!this.rotateData) {
160
+ this.setPath(data);
161
+ this.rotateData = Object.assign(Object.assign({}, data), { rotation: 0 });
162
+ interaction.emit(core.RotateEvent.START, this.rotateData);
163
+ }
164
+ data.path = this.rotateData.path;
165
+ interaction.emit(core.RotateEvent.BEFORE_ROTATE, data);
166
+ interaction.emit(core.RotateEvent.ROTATE, data);
167
+ this.transformEndWait();
168
+ }
169
+ setPath(data) {
170
+ const { interaction } = this;
171
+ const { path } = interaction.selector.getByPoint(data, interaction.hitRadius);
172
+ data.path = path;
173
+ interaction.cancelHover();
174
+ }
175
+ transformEndWait() {
176
+ clearTimeout(this.transformTimer);
177
+ this.transformTimer = setTimeout(() => {
178
+ this.transformEnd();
179
+ }, this.interaction.p.transformTime);
180
+ }
181
+ transformEnd() {
182
+ const { interaction, moveData, zoomData, rotateData } = this;
183
+ if (moveData)
184
+ interaction.emit(core.MoveEvent.END, moveData);
185
+ if (zoomData)
186
+ interaction.emit(core.ZoomEvent.END, zoomData);
187
+ if (rotateData)
188
+ interaction.emit(core.RotateEvent.END, rotateData);
189
+ this.reset();
190
+ }
191
+ reset() {
192
+ this.zoomData = this.moveData = this.rotateData = null;
193
+ }
194
+ destroy() {
195
+ this.reset();
196
+ }
197
+ }
198
+
199
+ const leafer = core.Leafer.prototype;
200
+ const bounds = new core.Bounds();
201
+ leafer.initType = function (type) {
202
+ LeaferTypeCreator.run(type, this);
203
+ };
204
+ leafer.getValidMove = function (moveX, moveY) {
205
+ const { scroll, disabled } = this.app.config.move;
206
+ if (scroll) {
207
+ const type = scroll === true ? '' : scroll;
208
+ if (type.includes('x'))
209
+ moveX = moveX || moveY, moveY = 0;
210
+ else if (type.includes('y'))
211
+ moveY = moveY || moveX, moveX = 0;
212
+ else
213
+ Math.abs(moveX) > Math.abs(moveY) ? moveY = 0 : moveX = 0;
214
+ if (type.includes('limit')) {
215
+ const { x, y, width, height } = bounds.set(this.__world).addPoint(this.zoomLayer);
216
+ const right = x + width - this.width, bottom = y + height - this.height;
217
+ if (x >= 0 && right <= 0)
218
+ moveX = 0;
219
+ else if (moveX > 0) {
220
+ if (x + moveX > 0)
221
+ moveX = -x;
222
+ }
223
+ else if (moveX < 0 && right + moveX < 0)
224
+ moveX = -right;
225
+ if (y >= 0 && bottom <= 0)
226
+ moveY = 0;
227
+ else if (moveY > 0) {
228
+ if (y + moveY > 0)
229
+ moveY = -y;
230
+ }
231
+ else if (moveY < 0 && bottom + moveY < 0)
232
+ moveY = -bottom;
233
+ }
234
+ }
235
+ return { x: disabled ? 0 : moveX, y: disabled ? 0 : moveY };
236
+ };
237
+ leafer.getValidScale = function (changeScale) {
238
+ const { scaleX } = this.zoomLayer.__, { min, max, disabled } = this.app.config.zoom, absScale = Math.abs(scaleX * changeScale);
239
+ if (min && absScale < min)
240
+ changeScale = min / scaleX;
241
+ else if (max && absScale > max)
242
+ changeScale = max / scaleX;
243
+ return disabled ? 1 : core.MathHelper.float(changeScale);
244
+ };
245
+
246
+ function getMoveEventData(move, event) {
247
+ return Object.assign(Object.assign({}, event), { moveX: move.x, moveY: move.y });
248
+ }
249
+ function getRotateEventData(rotation, event) {
250
+ return Object.assign(Object.assign({}, event), { rotation });
251
+ }
252
+ function getZoomEventData(scale, event) {
253
+ return Object.assign(Object.assign({}, event), { scale });
254
+ }
255
+ const interaction = core.InteractionBase.prototype;
256
+ interaction.createTransformer = function () {
257
+ this.transformer = new Transformer(this);
258
+ };
259
+ interaction.move = function (data) {
260
+ this.transformer.move(data);
261
+ };
262
+ interaction.zoom = function (data) {
263
+ this.transformer.zoom(data);
264
+ };
265
+ interaction.rotate = function (data) {
266
+ this.transformer.rotate(data);
267
+ };
268
+ interaction.transformEnd = function () {
269
+ this.transformer.transformEnd();
270
+ };
271
+ interaction.wheel = function (data) {
272
+ const { wheel } = this.config;
273
+ if (wheel.disabled)
274
+ return;
275
+ const scale = wheel.getScale ? wheel.getScale(data, wheel) : WheelEventHelper.getScale(data, wheel);
276
+ scale !== 1 ? this.zoom(getZoomEventData(scale, data)) : this.move(getMoveEventData(wheel.getMove ? wheel.getMove(data, wheel) : WheelEventHelper.getMove(data, wheel), data));
277
+ };
278
+ interaction.multiTouch = function (data, list) {
279
+ if (this.config.multiTouch.disabled)
280
+ return;
281
+ const { move, rotation, scale, center } = MultiTouchHelper.getData(list);
282
+ Object.assign(data, center);
283
+ this.rotate(getRotateEventData(rotation, data));
284
+ this.zoom(getZoomEventData(scale, data));
285
+ this.move(getMoveEventData(move, data));
286
+ };
287
+
288
+ const dragger = core.Dragger.prototype;
289
+ const { abs } = Math;
290
+ dragger.checkDragEndAnimate = function (data, speed) {
291
+ const { moveX, moveY } = this.dragData;
292
+ const absMoveX = abs(moveX), absMoveY = abs(moveY), minMove = speed ? 1 : 0.1;
293
+ const dragAnimate = this.interaction.m.dragAnimate && this.canAnimate && this.moving && (absMoveX > minMove || absMoveY > minMove);
294
+ if (dragAnimate) {
295
+ const inertia = data.pointerType === 'touch' ? 3 : 1, maxMove = 70;
296
+ speed = speed ? 0.95 : inertia;
297
+ if (absMoveX * speed > maxMove)
298
+ speed = maxMove / absMoveX;
299
+ else if (absMoveY * speed > maxMove)
300
+ speed = maxMove / absMoveY;
301
+ data = Object.assign({}, data);
302
+ core.PointHelper.move(data, moveX * speed, moveY * speed);
303
+ this.drag(data);
304
+ this.animate(() => { this.dragEnd(data, 1); });
305
+ }
306
+ return dragAnimate;
307
+ };
308
+ dragger.animate = function (func, off) {
309
+ const animateWait = func || this.animateWait;
310
+ if (animateWait)
311
+ this.interaction.target.nextRender(animateWait, null, off);
312
+ this.animateWait = func;
313
+ };
314
+ dragger.checkDragOut = function (data) {
315
+ const { interaction } = this;
316
+ this.autoMoveCancel();
317
+ if (this.dragging && !interaction.shrinkCanvasBounds.hitPoint(data))
318
+ this.autoMoveOnDragOut(data);
319
+ };
320
+ dragger.autoMoveOnDragOut = function (data) {
321
+ const { interaction, downData, canDragOut } = this;
322
+ const { autoDistance, dragOut } = interaction.m;
323
+ if (!dragOut || !canDragOut || !autoDistance)
324
+ return;
325
+ const bounds = interaction.shrinkCanvasBounds;
326
+ const { x, y } = bounds;
327
+ const right = core.BoundsHelper.maxX(bounds);
328
+ const bottom = core.BoundsHelper.maxY(bounds);
329
+ const moveX = data.x < x ? autoDistance : (right < data.x ? -autoDistance : 0);
330
+ const moveY = data.y < y ? autoDistance : (bottom < data.y ? -autoDistance : 0);
331
+ let totalX = 0, totalY = 0;
332
+ this.autoMoveTimer = setInterval(() => {
333
+ totalX += moveX;
334
+ totalY += moveY;
335
+ core.PointHelper.move(downData, moveX, moveY);
336
+ core.PointHelper.move(this.dragData, moveX, moveY);
337
+ interaction.move(Object.assign(Object.assign({}, data), { moveX, moveY, totalX, totalY, moveType: 'drag' }));
338
+ interaction.pointerMoveReal(data);
339
+ }, 10);
340
+ };
341
+ dragger.autoMoveCancel = function () {
342
+ if (this.autoMoveTimer) {
343
+ clearInterval(this.autoMoveTimer);
344
+ this.autoMoveTimer = 0;
345
+ }
346
+ };
347
+
348
+ exports.LeaferTypeCreator = LeaferTypeCreator;
349
+ exports.MultiTouchHelper = MultiTouchHelper;
350
+ exports.Transformer = Transformer;
351
+ exports.WheelEventHelper = WheelEventHelper;
352
+ exports.addViewport = addViewport;
353
+ exports.addViewportConfig = addViewportConfig;
354
+
355
+ return exports;
356
+
357
+ })({}, LeaferUI);
@@ -0,0 +1 @@
1
+ "use strict";var t=require("@leafer-ui/core");function e(e,a,i){o(e.parentApp?e.parentApp:e,a),e.isApp||i||e.__eventIds.push(e.on_(t.MoveEvent.BEFORE_MOVE,(t=>{e.zoomLayer.move(e.getValidMove(t.moveX,t.moveY))})),e.on_(t.ZoomEvent.BEFORE_ZOOM,(o=>{const{zoomLayer:a}=e,i=e.getValidScale(o.scale);1!==i&&(t.PointHelper.scaleOf(a,o,i),a.scale=a.__.scaleX*i)})))}function o(e,o){o&&t.DataHelper.assign(e.config,o),t.DataHelper.assign(e.config,{wheel:{preventDefault:!0},touch:{preventDefault:!0},pointer:{preventDefaultMenu:!0}},e.userConfig)}const a=t.Debug.get("LeaferTypeCreator"),i={list:{},register(t,e){n[t]&&a.repeat(t),n[t]=e},run(t,e){const o=n[t];o&&o(e)}},{list:n,register:s}=i;s("viewport",e),s("custom",(function(t){e(t,null,!0)})),s("design",(function(t){e(t,{zoom:{min:.01,max:256},move:{holdSpaceKey:!0,holdMiddleKey:!0}})})),s("document",(function(t){e(t,{zoom:{min:1},move:{scroll:"limit"}})}));const r={getData(e){const o=e[0],a=e[1],i=t.PointHelper.getCenter(o.from,a.from),n=t.PointHelper.getCenter(o.to,a.to),s={x:n.x-i.x,y:n.y-i.y},r=t.PointHelper.getDistance(o.from,a.from);return{move:s,scale:t.PointHelper.getDistance(o.to,a.to)/r,rotation:t.PointHelper.getRotation(o.from,a.from,o.to,a.to),center:n}}},c={getMove(t,e){let{moveSpeed:o}=e,{deltaX:a,deltaY:i}=t;return t.shiftKey&&!a&&(a=i,i=0),a>50&&(a=Math.max(50,a/3)),i>50&&(i=Math.max(50,i/3)),{x:-a*o*2,y:-i*o*2}},getScale(e,o){let a,i=1,{zoomMode:n,zoomSpeed:s}=o;const r=e.deltaY||e.deltaX;if(n?(a="mouse"===n||!e.deltaX&&(t.Platform.intWheelDeltaY?Math.abs(r)>17:Math.ceil(r)!==r),(e.shiftKey||e.metaKey||e.ctrlKey)&&(a=!0)):a=!e.shiftKey&&(e.metaKey||e.ctrlKey),a){s=t.MathHelper.within(s,0,1);i=1-r/(4*(e.deltaY?o.delta.y:o.delta.x))*s,i<.5&&(i=.5),i>=1.5&&(i=1.5)}return i}};class m{get transforming(){return!!(this.moveData||this.zoomData||this.rotateData)}constructor(t){this.interaction=t}move(e){const{interaction:o}=this;e.moveType||(e.moveType="move"),this.moveData||(this.setPath(e),this.moveData=Object.assign(Object.assign({},e),{moveX:0,moveY:0}),o.emit(t.MoveEvent.START,this.moveData)),e.path=this.moveData.path,o.emit(t.MoveEvent.BEFORE_MOVE,e),o.emit(t.MoveEvent.MOVE,e),this.transformEndWait()}zoom(e){const{interaction:o}=this;this.zoomData||(this.setPath(e),this.zoomData=Object.assign(Object.assign({},e),{scale:1}),o.emit(t.ZoomEvent.START,this.zoomData)),e.path=this.zoomData.path,o.emit(t.ZoomEvent.BEFORE_ZOOM,e),o.emit(t.ZoomEvent.ZOOM,e),this.transformEndWait()}rotate(e){const{interaction:o}=this;this.rotateData||(this.setPath(e),this.rotateData=Object.assign(Object.assign({},e),{rotation:0}),o.emit(t.RotateEvent.START,this.rotateData)),e.path=this.rotateData.path,o.emit(t.RotateEvent.BEFORE_ROTATE,e),o.emit(t.RotateEvent.ROTATE,e),this.transformEndWait()}setPath(t){const{interaction:e}=this,{path:o}=e.selector.getByPoint(t,e.hitRadius);t.path=o,e.cancelHover()}transformEndWait(){clearTimeout(this.transformTimer),this.transformTimer=setTimeout((()=>{this.transformEnd()}),this.interaction.p.transformTime)}transformEnd(){const{interaction:e,moveData:o,zoomData:a,rotateData:i}=this;o&&e.emit(t.MoveEvent.END,o),a&&e.emit(t.ZoomEvent.END,a),i&&e.emit(t.RotateEvent.END,i),this.reset()}reset(){this.zoomData=this.moveData=this.rotateData=null}destroy(){this.reset()}}const h=t.Leafer.prototype,l=new t.Bounds;function u(t,e){return Object.assign(Object.assign({},e),{moveX:t.x,moveY:t.y})}function v(t,e){return Object.assign(Object.assign({},e),{scale:t})}h.initType=function(t){i.run(t,this)},h.getValidMove=function(t,e){const{scroll:o,disabled:a}=this.app.config.move;if(o){const a=!0===o?"":o;if(a.includes("x")?(t=t||e,e=0):a.includes("y")?(e=e||t,t=0):Math.abs(t)>Math.abs(e)?e=0:t=0,a.includes("limit")){const{x:o,y:a,width:i,height:n}=l.set(this.__world).addPoint(this.zoomLayer),s=o+i-this.width,r=a+n-this.height;o>=0&&s<=0?t=0:t>0?o+t>0&&(t=-o):t<0&&s+t<0&&(t=-s),a>=0&&r<=0?e=0:e>0?a+e>0&&(e=-a):e<0&&r+e<0&&(e=-r)}}return{x:a?0:t,y:a?0:e}},h.getValidScale=function(e){const{scaleX:o}=this.zoomLayer.__,{min:a,max:i,disabled:n}=this.app.config.zoom,s=Math.abs(o*e);return a&&s<a?e=a/o:i&&s>i&&(e=i/o),n?1:t.MathHelper.float(e)};const f=t.InteractionBase.prototype;f.createTransformer=function(){this.transformer=new m(this)},f.move=function(t){this.transformer.move(t)},f.zoom=function(t){this.transformer.zoom(t)},f.rotate=function(t){this.transformer.rotate(t)},f.transformEnd=function(){this.transformer.transformEnd()},f.wheel=function(t){const{wheel:e}=this.config;if(e.disabled)return;const o=e.getScale?e.getScale(t,e):c.getScale(t,e);1!==o?this.zoom(v(o,t)):this.move(u(e.getMove?e.getMove(t,e):c.getMove(t,e),t))},f.multiTouch=function(t,e){if(this.config.multiTouch.disabled)return;const{move:o,rotation:a,scale:i,center:n}=r.getData(e);Object.assign(t,n),this.rotate(function(t,e){return Object.assign(Object.assign({},e),{rotation:t})}(a,t)),this.zoom(v(i,t)),this.move(u(o,t))};const g=t.Dragger.prototype,{abs:p}=Math;g.checkDragEndAnimate=function(e,o){const{moveX:a,moveY:i}=this.dragData,n=p(a),s=p(i),r=o?1:.1,c=this.interaction.m.dragAnimate&&this.canAnimate&&this.moving&&(n>r||s>r);if(c){const r="touch"===e.pointerType?3:1,c=70;n*(o=o?.95:r)>c?o=c/n:s*o>c&&(o=c/s),e=Object.assign({},e),t.PointHelper.move(e,a*o,i*o),this.drag(e),this.animate((()=>{this.dragEnd(e,1)}))}return c},g.animate=function(t,e){const o=t||this.animateWait;o&&this.interaction.target.nextRender(o,null,e),this.animateWait=t},g.checkDragOut=function(t){const{interaction:e}=this;this.autoMoveCancel(),this.dragging&&!e.shrinkCanvasBounds.hitPoint(t)&&this.autoMoveOnDragOut(t)},g.autoMoveOnDragOut=function(e){const{interaction:o,downData:a,canDragOut:i}=this,{autoDistance:n,dragOut:s}=o.m;if(!s||!i||!n)return;const r=o.shrinkCanvasBounds,{x:c,y:m}=r,h=t.BoundsHelper.maxX(r),l=t.BoundsHelper.maxY(r),u=e.x<c?n:h<e.x?-n:0,v=e.y<m?n:l<e.y?-n:0;let f=0,g=0;this.autoMoveTimer=setInterval((()=>{f+=u,g+=v,t.PointHelper.move(a,u,v),t.PointHelper.move(this.dragData,u,v),o.move(Object.assign(Object.assign({},e),{moveX:u,moveY:v,totalX:f,totalY:g,moveType:"drag"})),o.pointerMoveReal(e)}),10)},g.autoMoveCancel=function(){this.autoMoveTimer&&(clearInterval(this.autoMoveTimer),this.autoMoveTimer=0)},exports.LeaferTypeCreator=i,exports.MultiTouchHelper=r,exports.Transformer=m,exports.WheelEventHelper=c,exports.addViewport=e,exports.addViewportConfig=o;
@@ -0,0 +1 @@
1
+ this.LeaferIN=this.LeaferIN||{},this.LeaferIN.viewport=function(t,e){"use strict";function o(t,o,i){a(t.parentApp?t.parentApp:t,o),t.isApp||i||t.__eventIds.push(t.on_(e.MoveEvent.BEFORE_MOVE,(e=>{t.zoomLayer.move(t.getValidMove(e.moveX,e.moveY))})),t.on_(e.ZoomEvent.BEFORE_ZOOM,(o=>{const{zoomLayer:a}=t,i=t.getValidScale(o.scale);1!==i&&(e.PointHelper.scaleOf(a,o,i),a.scale=a.__.scaleX*i)})))}function a(t,o){o&&e.DataHelper.assign(t.config,o),e.DataHelper.assign(t.config,{wheel:{preventDefault:!0},touch:{preventDefault:!0},pointer:{preventDefaultMenu:!0}},t.userConfig)}const i=e.Debug.get("LeaferTypeCreator"),n={list:{},register(t,e){s[t]&&i.repeat(t),s[t]=e},run(t,e){const o=s[t];o&&o(e)}},{list:s,register:r}=n;r("viewport",o),r("custom",(function(t){o(t,null,!0)})),r("design",(function(t){o(t,{zoom:{min:.01,max:256},move:{holdSpaceKey:!0,holdMiddleKey:!0}})})),r("document",(function(t){o(t,{zoom:{min:1},move:{scroll:"limit"}})}));const c={getData(t){const o=t[0],a=t[1],i=e.PointHelper.getCenter(o.from,a.from),n=e.PointHelper.getCenter(o.to,a.to),s={x:n.x-i.x,y:n.y-i.y},r=e.PointHelper.getDistance(o.from,a.from);return{move:s,scale:e.PointHelper.getDistance(o.to,a.to)/r,rotation:e.PointHelper.getRotation(o.from,a.from,o.to,a.to),center:n}}},m={getMove(t,e){let{moveSpeed:o}=e,{deltaX:a,deltaY:i}=t;return t.shiftKey&&!a&&(a=i,i=0),a>50&&(a=Math.max(50,a/3)),i>50&&(i=Math.max(50,i/3)),{x:-a*o*2,y:-i*o*2}},getScale(t,o){let a,i=1,{zoomMode:n,zoomSpeed:s}=o;const r=t.deltaY||t.deltaX;if(n?(a="mouse"===n||!t.deltaX&&(e.Platform.intWheelDeltaY?Math.abs(r)>17:Math.ceil(r)!==r),(t.shiftKey||t.metaKey||t.ctrlKey)&&(a=!0)):a=!t.shiftKey&&(t.metaKey||t.ctrlKey),a){s=e.MathHelper.within(s,0,1);i=1-r/(4*(t.deltaY?o.delta.y:o.delta.x))*s,i<.5&&(i=.5),i>=1.5&&(i=1.5)}return i}};class h{get transforming(){return!!(this.moveData||this.zoomData||this.rotateData)}constructor(t){this.interaction=t}move(t){const{interaction:o}=this;t.moveType||(t.moveType="move"),this.moveData||(this.setPath(t),this.moveData=Object.assign(Object.assign({},t),{moveX:0,moveY:0}),o.emit(e.MoveEvent.START,this.moveData)),t.path=this.moveData.path,o.emit(e.MoveEvent.BEFORE_MOVE,t),o.emit(e.MoveEvent.MOVE,t),this.transformEndWait()}zoom(t){const{interaction:o}=this;this.zoomData||(this.setPath(t),this.zoomData=Object.assign(Object.assign({},t),{scale:1}),o.emit(e.ZoomEvent.START,this.zoomData)),t.path=this.zoomData.path,o.emit(e.ZoomEvent.BEFORE_ZOOM,t),o.emit(e.ZoomEvent.ZOOM,t),this.transformEndWait()}rotate(t){const{interaction:o}=this;this.rotateData||(this.setPath(t),this.rotateData=Object.assign(Object.assign({},t),{rotation:0}),o.emit(e.RotateEvent.START,this.rotateData)),t.path=this.rotateData.path,o.emit(e.RotateEvent.BEFORE_ROTATE,t),o.emit(e.RotateEvent.ROTATE,t),this.transformEndWait()}setPath(t){const{interaction:e}=this,{path:o}=e.selector.getByPoint(t,e.hitRadius);t.path=o,e.cancelHover()}transformEndWait(){clearTimeout(this.transformTimer),this.transformTimer=setTimeout((()=>{this.transformEnd()}),this.interaction.p.transformTime)}transformEnd(){const{interaction:t,moveData:o,zoomData:a,rotateData:i}=this;o&&t.emit(e.MoveEvent.END,o),a&&t.emit(e.ZoomEvent.END,a),i&&t.emit(e.RotateEvent.END,i),this.reset()}reset(){this.zoomData=this.moveData=this.rotateData=null}destroy(){this.reset()}}const l=e.Leafer.prototype,u=new e.Bounds;function v(t,e){return Object.assign(Object.assign({},e),{moveX:t.x,moveY:t.y})}function f(t,e){return Object.assign(Object.assign({},e),{scale:t})}l.initType=function(t){n.run(t,this)},l.getValidMove=function(t,e){const{scroll:o,disabled:a}=this.app.config.move;if(o){const a=!0===o?"":o;if(a.includes("x")?(t=t||e,e=0):a.includes("y")?(e=e||t,t=0):Math.abs(t)>Math.abs(e)?e=0:t=0,a.includes("limit")){const{x:o,y:a,width:i,height:n}=u.set(this.__world).addPoint(this.zoomLayer),s=o+i-this.width,r=a+n-this.height;o>=0&&s<=0?t=0:t>0?o+t>0&&(t=-o):t<0&&s+t<0&&(t=-s),a>=0&&r<=0?e=0:e>0?a+e>0&&(e=-a):e<0&&r+e<0&&(e=-r)}}return{x:a?0:t,y:a?0:e}},l.getValidScale=function(t){const{scaleX:o}=this.zoomLayer.__,{min:a,max:i,disabled:n}=this.app.config.zoom,s=Math.abs(o*t);return a&&s<a?t=a/o:i&&s>i&&(t=i/o),n?1:e.MathHelper.float(t)};const g=e.InteractionBase.prototype;g.createTransformer=function(){this.transformer=new h(this)},g.move=function(t){this.transformer.move(t)},g.zoom=function(t){this.transformer.zoom(t)},g.rotate=function(t){this.transformer.rotate(t)},g.transformEnd=function(){this.transformer.transformEnd()},g.wheel=function(t){const{wheel:e}=this.config;if(e.disabled)return;const o=e.getScale?e.getScale(t,e):m.getScale(t,e);1!==o?this.zoom(f(o,t)):this.move(v(e.getMove?e.getMove(t,e):m.getMove(t,e),t))},g.multiTouch=function(t,e){if(this.config.multiTouch.disabled)return;const{move:o,rotation:a,scale:i,center:n}=c.getData(e);Object.assign(t,n),this.rotate(function(t,e){return Object.assign(Object.assign({},e),{rotation:t})}(a,t)),this.zoom(f(i,t)),this.move(v(o,t))};const d=e.Dragger.prototype,{abs:p}=Math;return d.checkDragEndAnimate=function(t,o){const{moveX:a,moveY:i}=this.dragData,n=p(a),s=p(i),r=o?1:.1,c=this.interaction.m.dragAnimate&&this.canAnimate&&this.moving&&(n>r||s>r);if(c){const r="touch"===t.pointerType?3:1,c=70;n*(o=o?.95:r)>c?o=c/n:s*o>c&&(o=c/s),t=Object.assign({},t),e.PointHelper.move(t,a*o,i*o),this.drag(t),this.animate((()=>{this.dragEnd(t,1)}))}return c},d.animate=function(t,e){const o=t||this.animateWait;o&&this.interaction.target.nextRender(o,null,e),this.animateWait=t},d.checkDragOut=function(t){const{interaction:e}=this;this.autoMoveCancel(),this.dragging&&!e.shrinkCanvasBounds.hitPoint(t)&&this.autoMoveOnDragOut(t)},d.autoMoveOnDragOut=function(t){const{interaction:o,downData:a,canDragOut:i}=this,{autoDistance:n,dragOut:s}=o.m;if(!s||!i||!n)return;const r=o.shrinkCanvasBounds,{x:c,y:m}=r,h=e.BoundsHelper.maxX(r),l=e.BoundsHelper.maxY(r),u=t.x<c?n:h<t.x?-n:0,v=t.y<m?n:l<t.y?-n:0;let f=0,g=0;this.autoMoveTimer=setInterval((()=>{f+=u,g+=v,e.PointHelper.move(a,u,v),e.PointHelper.move(this.dragData,u,v),o.move(Object.assign(Object.assign({},t),{moveX:u,moveY:v,totalX:f,totalY:g,moveType:"drag"})),o.pointerMoveReal(t)}),10)},d.autoMoveCancel=function(){this.autoMoveTimer&&(clearInterval(this.autoMoveTimer),this.autoMoveTimer=0)},t.LeaferTypeCreator=n,t.MultiTouchHelper=c,t.Transformer=h,t.WheelEventHelper=m,t.addViewport=o,t.addViewportConfig=a,t}({},LeaferUI);
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@leafer-in/viewport",
3
+ "version": "1.1.1",
4
+ "description": "@leafer-in/viewport",
5
+ "author": "Chao (Leafer) Wan",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "dist/viewport.esm.js",
9
+ "exports": {
10
+ "import": "./dist/viewport.esm.js",
11
+ "require": "./dist/viewport.cjs",
12
+ "types": "./types/index.d.ts"
13
+ },
14
+ "types": "types/index.d.ts",
15
+ "unpkg": "dist/viewport.js",
16
+ "jsdelivr": "dist/viewport.js",
17
+ "files": [
18
+ "src",
19
+ "types",
20
+ "dist"
21
+ ],
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/leaferjs/leafer-in.git"
25
+ },
26
+ "homepage": "https://github.com/leaferjs/leafer-in/tree/main/packages/viewport",
27
+ "bugs": "https://github.com/leaferjs/leafer-in/issues",
28
+ "keywords": [
29
+ "leafer viewport",
30
+ "leafer-viewport",
31
+ "leafer-in",
32
+ "viewport",
33
+ "leafer-ui",
34
+ "leaferjs"
35
+ ],
36
+ "peerDependencies": {
37
+ "@leafer-ui/core": "^1.1.1",
38
+ "@leafer-ui/interface": "^1.1.1",
39
+ "@leafer-in/interface": "^1.1.1"
40
+ }
41
+ }
package/src/Leafer.ts ADDED
@@ -0,0 +1,46 @@
1
+ import { ILeaferType, IPointData } from '@leafer-ui/interface'
2
+
3
+ import { Leafer, Bounds, MathHelper } from '@leafer-ui/core'
4
+
5
+ import { LeaferTypeCreator } from './LeaferTypeCreator'
6
+
7
+
8
+ const leafer = Leafer.prototype
9
+ const bounds = new Bounds()
10
+
11
+ leafer.initType = function (type: ILeaferType) {
12
+ LeaferTypeCreator.run(type, this)
13
+ }
14
+
15
+ leafer.getValidMove = function (moveX: number, moveY: number): IPointData {
16
+ const { scroll, disabled } = this.app.config.move
17
+
18
+ if (scroll) {
19
+ const type = scroll === true ? '' : scroll
20
+
21
+ if (type.includes('x')) moveX = moveX || moveY, moveY = 0
22
+ else if (type.includes('y')) moveY = moveY || moveX, moveX = 0
23
+ else Math.abs(moveX) > Math.abs(moveY) ? moveY = 0 : moveX = 0
24
+
25
+ if (type.includes('limit')) {
26
+ const { x, y, width, height } = bounds.set(this.__world).addPoint(this.zoomLayer as IPointData)
27
+ const right = x + width - this.width, bottom = y + height - this.height
28
+
29
+ if (x >= 0 && right <= 0) moveX = 0 // includeX
30
+ else if (moveX > 0) { if (x + moveX > 0) moveX = -x }
31
+ else if (moveX < 0 && right + moveX < 0) moveX = -right
32
+
33
+ if (y >= 0 && bottom <= 0) moveY = 0 // includeY
34
+ else if (moveY > 0) { if (y + moveY > 0) moveY = -y }
35
+ else if (moveY < 0 && bottom + moveY < 0) moveY = -bottom
36
+ }
37
+ }
38
+ return { x: disabled ? 0 : moveX, y: disabled ? 0 : moveY }
39
+ }
40
+
41
+ leafer.getValidScale = function (changeScale: number): number {
42
+ const { scaleX } = this.zoomLayer.__, { min, max, disabled } = this.app.config.zoom, absScale = Math.abs(scaleX * changeScale)
43
+ if (min && absScale < min) changeScale = min / scaleX
44
+ else if (max && absScale > max) changeScale = max / scaleX
45
+ return disabled ? 1 : MathHelper.float(changeScale)
46
+ }
@@ -0,0 +1,34 @@
1
+ import { ILeaferBase, ILeaferTypeList, ILeaferTypeFunction } from '@leafer-ui/interface'
2
+
3
+ import { Debug } from '@leafer-ui/core'
4
+
5
+ import { addViewport } from './type/viewport'
6
+ import { custom } from './type/custom'
7
+ import { design } from './type/design'
8
+ import { document } from './type/document'
9
+
10
+
11
+ const debug = Debug.get('LeaferTypeCreator')
12
+
13
+ export const LeaferTypeCreator = {
14
+
15
+ list: {} as ILeaferTypeList,
16
+
17
+ register(name: string, fn: ILeaferTypeFunction): void {
18
+ list[name] && debug.repeat(name)
19
+ list[name] = fn
20
+ },
21
+
22
+ run(name: string, leafer: ILeaferBase): void {
23
+ const fn = list[name]
24
+ fn && fn(leafer)
25
+ }
26
+
27
+ }
28
+
29
+ const { list, register } = LeaferTypeCreator
30
+
31
+ register('viewport', addViewport)
32
+ register('custom', custom)
33
+ register('design', design)
34
+ register('document', document)
package/src/index.ts ADDED
@@ -0,0 +1,9 @@
1
+ export { LeaferTypeCreator } from './LeaferTypeCreator'
2
+ export { addViewport, addViewportConfig } from './type/viewport'
3
+ export { MultiTouchHelper } from './interaction/MultiTouchHelper'
4
+ export { WheelEventHelper } from './interaction/WheelEventHelper'
5
+ export { Transformer } from './interaction/Transformer'
6
+
7
+ import './Leafer'
8
+ import './interaction/Interaction'
9
+ import './interaction/Dragger'
@@ -0,0 +1,73 @@
1
+ import { IPointerEvent, IFunction } from '@leafer-ui/interface'
2
+
3
+ import { Dragger, BoundsHelper, PointHelper } from '@leafer-ui/core'
4
+
5
+
6
+ const dragger = Dragger.prototype
7
+ const { abs } = Math
8
+
9
+ dragger.checkDragEndAnimate = function (data: IPointerEvent, speed?: number): boolean {
10
+ const { moveX, moveY } = this.dragData
11
+ const absMoveX = abs(moveX), absMoveY = abs(moveY), minMove = speed ? 1 : 0.1
12
+ const dragAnimate = this.interaction.m.dragAnimate && this.canAnimate && this.moving && (absMoveX > minMove || absMoveY > minMove)
13
+
14
+ if (dragAnimate) {
15
+ const inertia = data.pointerType === 'touch' ? 3 : 1, maxMove = 70
16
+ speed = speed ? 0.95 : inertia
17
+ if (absMoveX * speed > maxMove) speed = maxMove / absMoveX
18
+ else if (absMoveY * speed > maxMove) speed = maxMove / absMoveY
19
+
20
+ data = { ...data }
21
+ PointHelper.move(data, moveX * speed, moveY * speed)
22
+
23
+ this.drag(data)
24
+ this.animate(() => { this.dragEnd(data, 1) })
25
+ }
26
+
27
+ return dragAnimate
28
+ }
29
+
30
+ dragger.animate = function (func?: IFunction, off?: 'off'): void { // dragEnd animation
31
+ const animateWait = func || this.animateWait
32
+ if (animateWait) this.interaction.target.nextRender(animateWait, null, off)
33
+ this.animateWait = func
34
+ }
35
+
36
+ dragger.checkDragOut = function (data: IPointerEvent): void {
37
+ const { interaction } = this
38
+ this.autoMoveCancel()
39
+ if (this.dragging && !interaction.shrinkCanvasBounds.hitPoint(data)) this.autoMoveOnDragOut(data)
40
+ }
41
+
42
+ dragger.autoMoveOnDragOut = function (data: IPointerEvent): void {
43
+ const { interaction, downData, canDragOut } = this
44
+ const { autoDistance, dragOut } = interaction.m
45
+ if (!dragOut || !canDragOut || !autoDistance) return
46
+
47
+ const bounds = interaction.shrinkCanvasBounds
48
+ const { x, y } = bounds
49
+ const right = BoundsHelper.maxX(bounds)
50
+ const bottom = BoundsHelper.maxY(bounds)
51
+
52
+ const moveX = data.x < x ? autoDistance : (right < data.x ? -autoDistance : 0)
53
+ const moveY = data.y < y ? autoDistance : (bottom < data.y ? -autoDistance : 0)
54
+ let totalX = 0, totalY = 0
55
+
56
+ this.autoMoveTimer = setInterval(() => {
57
+ totalX += moveX
58
+ totalY += moveY
59
+
60
+ PointHelper.move(downData, moveX, moveY)
61
+ PointHelper.move(this.dragData, moveX, moveY)
62
+
63
+ interaction.move({ ...data, moveX, moveY, totalX, totalY, moveType: 'drag' })
64
+ interaction.pointerMoveReal(data)
65
+ }, 10)
66
+ }
67
+
68
+ dragger.autoMoveCancel = function (): void {
69
+ if (this.autoMoveTimer) {
70
+ clearInterval(this.autoMoveTimer)
71
+ this.autoMoveTimer = 0
72
+ }
73
+ }
@@ -0,0 +1,63 @@
1
+ import { IMoveEvent, IZoomEvent, IRotateEvent, IWheelEvent, IUIEvent, IKeepTouchData, IPointData, IEvent } from '@leafer-ui/interface'
2
+
3
+ import { InteractionBase } from '@leafer-ui/core'
4
+
5
+ import { WheelEventHelper } from './WheelEventHelper'
6
+ import { Transformer } from './Transformer'
7
+ import { MultiTouchHelper } from './MultiTouchHelper'
8
+
9
+
10
+ function getMoveEventData(move: IPointData, event: IEvent): IMoveEvent {
11
+ return { ...event, moveX: move.x, moveY: move.y } as IMoveEvent
12
+ }
13
+
14
+ function getRotateEventData(rotation: number, event: IEvent): IRotateEvent {
15
+ return { ...event, rotation } as IRotateEvent
16
+ }
17
+
18
+ function getZoomEventData(scale: number, event: IEvent): IZoomEvent {
19
+ return { ...event, scale, } as IZoomEvent
20
+ }
21
+
22
+
23
+ const interaction = InteractionBase.prototype
24
+
25
+ interaction.createTransformer = function (): void {
26
+ this.transformer = new Transformer(this)
27
+ }
28
+
29
+ interaction.move = function (data: IMoveEvent): void {
30
+ this.transformer.move(data)
31
+ }
32
+
33
+ interaction.zoom = function (data: IZoomEvent): void {
34
+ this.transformer.zoom(data)
35
+ }
36
+
37
+ interaction.rotate = function (data: IRotateEvent): void {
38
+ this.transformer.rotate(data)
39
+ }
40
+
41
+ interaction.transformEnd = function (): void {
42
+ this.transformer.transformEnd()
43
+ }
44
+
45
+
46
+ interaction.wheel = function (data: IWheelEvent): void {
47
+ const { wheel } = this.config
48
+ if (wheel.disabled) return
49
+
50
+ const scale = wheel.getScale ? wheel.getScale(data, wheel) : WheelEventHelper.getScale(data, wheel)
51
+ scale !== 1 ? this.zoom(getZoomEventData(scale, data)) : this.move(getMoveEventData(wheel.getMove ? wheel.getMove(data, wheel) : WheelEventHelper.getMove(data, wheel), data))
52
+ }
53
+
54
+
55
+ interaction.multiTouch = function (data: IUIEvent, list: IKeepTouchData[]): void {
56
+ if (this.config.multiTouch.disabled) return
57
+ const { move, rotation, scale, center } = MultiTouchHelper.getData(list)
58
+ Object.assign(data, center)
59
+
60
+ this.rotate(getRotateEventData(rotation, data))
61
+ this.zoom(getZoomEventData(scale, data))
62
+ this.move(getMoveEventData(move, data))
63
+ }