@shijiu/jsview 1.9.719
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.
- package/dom/bin/jsview-browser-debug-dom.min.js +1 -0
- package/dom/bin/jsview-dom.min.js +1 -0
- package/dom/bin/jsview-engine-js-browser.min.js +1 -0
- package/dom/bin/jsview-forge-define.min.js +1 -0
- package/dom/browser-root-style.css +21 -0
- package/dom/jsv-browser-debug-dom.js +8 -0
- package/dom/jsv-dom.js +6 -0
- package/dom/jsv-engine-js-browser.js +6 -0
- package/dom/jsv-forge-define.js +6 -0
- package/dom/jsview-dom/README.md +5 -0
- package/dom/jsview-dom/package-lock.json-perfect +3898 -0
- package/dom/jsview-dom/package.json +23 -0
- package/dom/jsview-dom/rollup/browser-debug-dom.rollup.config.js +15 -0
- package/dom/jsview-dom/rollup/dom.rollup.config.js +14 -0
- package/dom/jsview-dom/rollup/engine-js-browser.rollup.config.js +14 -0
- package/dom/jsview-dom/rollup/forge-define.rollup.config.js +14 -0
- package/dom/jsview-dom/scripts/release_dist.sh +36 -0
- package/dom/jsview-dom/src/dom-browser-hook/HookDocument.js +118 -0
- package/dom/jsview-dom/src/dom-browser-hook/OriginDocument.js +19 -0
- package/dom/jsview-dom/src/dom-browser-hook/StyleFormatCheck.js +559 -0
- package/dom/jsview-dom/src/dom-browser-hook/index.js +6 -0
- package/dom/jsview-dom/src/dom-wrapper/ForgeExtension.js +226 -0
- package/dom/jsview-dom/src/dom-wrapper/JsViewForgeApp.js +85 -0
- package/dom/jsview-dom/src/dom-wrapper/JsViewProxy.js +51 -0
- package/dom/jsview-dom/src/dom-wrapper/event/AnimationEvent.js +7 -0
- package/dom/jsview-dom/src/dom-wrapper/event/Event.js +12 -0
- package/dom/jsview-dom/src/dom-wrapper/event/FocusEvent.js +9 -0
- package/dom/jsview-dom/src/dom-wrapper/event/KeyboardEvent.js +43 -0
- package/dom/jsview-dom/src/dom-wrapper/event/LoadEvent.js +8 -0
- package/dom/jsview-dom/src/dom-wrapper/index.js +16 -0
- package/dom/jsview-dom/src/dom-wrapper/node/AnchorElement.js +24 -0
- package/dom/jsview-dom/src/dom-wrapper/node/AudioElement.js +60 -0
- package/dom/jsview-dom/src/dom-wrapper/node/Comment.js +10 -0
- package/dom/jsview-dom/src/dom-wrapper/node/DivElement.js +498 -0
- package/dom/jsview-dom/src/dom-wrapper/node/Document.js +274 -0
- package/dom/jsview-dom/src/dom-wrapper/node/Element.js +852 -0
- package/dom/jsview-dom/src/dom-wrapper/node/FDivElement.js +48 -0
- package/dom/jsview-dom/src/dom-wrapper/node/HeadElement.js +47 -0
- package/dom/jsview-dom/src/dom-wrapper/node/ImageElement.js +203 -0
- package/dom/jsview-dom/src/dom-wrapper/node/JsvAudioTrackElement.js +22 -0
- package/dom/jsview-dom/src/dom-wrapper/node/JsvElement.js +40 -0
- package/dom/jsview-dom/src/dom-wrapper/node/LinkElement.js +48 -0
- package/dom/jsview-dom/src/dom-wrapper/node/MediaElement.js +230 -0
- package/dom/jsview-dom/src/dom-wrapper/node/Node.js +178 -0
- package/dom/jsview-dom/src/dom-wrapper/node/SVGElement.js +9 -0
- package/dom/jsview-dom/src/dom-wrapper/node/ScriptElement.js +45 -0
- package/dom/jsview-dom/src/dom-wrapper/node/StyleElement.js +33 -0
- package/dom/jsview-dom/src/dom-wrapper/node/StyleElementCache.js +41 -0
- package/dom/jsview-dom/src/dom-wrapper/node/Text.js +22 -0
- package/dom/jsview-dom/src/dom-wrapper/node/UnknownElement.js +4 -0
- package/dom/jsview-dom/src/dom-wrapper/node/VideoElement.js +237 -0
- package/dom/jsview-dom/src/dom-wrapper/style/BorderImage.js +25 -0
- package/dom/jsview-dom/src/dom-wrapper/style/Inset.js +26 -0
- package/dom/jsview-dom/src/dom-wrapper/style/JsvStyleVariable.js +65 -0
- package/dom/jsview-dom/src/dom-wrapper/style/KeyframeRule.js +11 -0
- package/dom/jsview-dom/src/dom-wrapper/style/StyleDeclaration.js +609 -0
- package/dom/jsview-dom/src/dom-wrapper/style/StyleSheet.js +51 -0
- package/dom/jsview-dom/src/dom-wrapper/style/StyleValue.js +385 -0
- package/dom/jsview-dom/src/dom-wrapper/style/TextStylePackMap.js +43 -0
- package/dom/jsview-dom/src/dom-wrapper/style/URL.js +144 -0
- package/dom/jsview-dom/src/dom-wrapper/utils/EventHandler.js +42 -0
- package/dom/jsview-dom/src/dom-wrapper/utils/FDivRoot.js +86 -0
- package/dom/jsview-dom/src/dom-wrapper/utils/JsvLazySyncCache.js +64 -0
- package/dom/jsview-dom/src/dom-wrapper/utils/Log.js +42 -0
- package/dom/jsview-dom/src/dom-wrapper/utils/MutationObserver.js +32 -0
- package/dom/jsview-dom/src/dom-wrapper/utils/focusableNode.js +715 -0
- package/dom/jsview-dom/src/engine-js/ForgeDefine.js +8 -0
- package/dom/jsview-dom/src/engine-js/ForgeExtensionDefine.js +14 -0
- package/dom/jsview-dom/src/engine-js/browser/PlatformUtils.js +100 -0
- package/dom/jsview-dom/src/engine-js/browser/animation_base.js +313 -0
- package/dom/jsview-dom/src/engine-js/browser/animation_keyframe.js +64 -0
- package/dom/jsview-dom/src/engine-js/browser/animation_progress.js +287 -0
- package/dom/jsview-dom/src/engine-js/browser/animation_proxy.js +906 -0
- package/dom/jsview-dom/src/engine-js/browser/apic_decoder/demux.js +143 -0
- package/dom/jsview-dom/src/engine-js/browser/apic_decoder/gifDecoder.js +12 -0
- package/dom/jsview-dom/src/engine-js/browser/apic_decoder/libwebp-0.6.0.min.js +160 -0
- package/dom/jsview-dom/src/engine-js/browser/console_log.js +25 -0
- package/dom/jsview-dom/src/engine-js/browser/dynamic_key_frames.js +95 -0
- package/dom/jsview-dom/src/engine-js/browser/easing.js +114 -0
- package/dom/jsview-dom/src/engine-js/browser/html_shared_tools/element_transform.js +122 -0
- package/dom/jsview-dom/src/engine-js/browser/html_shared_tools/gjk.js +450 -0
- package/dom/jsview-dom/src/engine-js/browser/html_shared_tools/mat.js +102 -0
- package/dom/jsview-dom/src/engine-js/browser/html_shared_tools/range_model.js +296 -0
- package/dom/jsview-dom/src/engine-js/browser/html_shared_tools/test_collide.js +10 -0
- package/dom/jsview-dom/src/engine-js/browser/index.js +38 -0
- package/dom/jsview-dom/src/engine-js/browser/latex_parse.js +336 -0
- package/dom/jsview-dom/src/engine-js/browser/layout_params.js +113 -0
- package/dom/jsview-dom/src/engine-js/browser/layout_view.js +3545 -0
- package/dom/jsview-dom/src/engine-js/browser/layout_view_debug.js +15 -0
- package/dom/jsview-dom/src/engine-js/browser/media.js +379 -0
- package/dom/jsview-dom/src/engine-js/browser/page_base.js +941 -0
- package/dom/jsview-dom/src/engine-js/browser/particle_view.js +526 -0
- package/dom/jsview-dom/src/engine-js/browser/platform_timer.js +61 -0
- package/dom/jsview-dom/src/engine-js/browser/react_utils.js +5 -0
- package/dom/jsview-dom/src/engine-js/browser/rect_utils.js +91 -0
- package/dom/jsview-dom/src/engine-js/browser/render_bridge.js +128 -0
- package/dom/jsview-dom/src/engine-js/browser/render_texture_proxy.js +155 -0
- package/dom/jsview-dom/src/engine-js/browser/renderer_deprecated.js +75 -0
- package/dom/jsview-dom/src/engine-js/browser/sound_pool.js +139 -0
- package/dom/jsview-dom/src/engine-js/browser/steps_animation.js +192 -0
- package/dom/jsview-dom/src/engine-js/browser/text_style_cache.js +454 -0
- package/dom/jsview-dom/src/engine-js/browser/text_utils.js +299 -0
- package/dom/jsview-dom/src/engine-js/browser/text_view.js +428 -0
- package/dom/jsview-dom/src/engine-js/browser/texture_manager.js +1060 -0
- package/dom/jsview-dom/src/engine-js/browser/url.js +69 -0
- package/dom/jsview-dom/src/engine-js/browser/velocity.js +40 -0
- package/dom/jsview-dom/src/engine-js/browser/view_sensor/autofroze_sensor.js +77 -0
- package/dom/jsview-dom/src/engine-js/browser/view_sensor/drag_impact_sensor.js +67 -0
- package/dom/jsview-dom/src/engine-js/browser/view_sensor/impact_sensor.js +98 -0
- package/dom/jsview-dom/src/engine-js/browser/view_sensor/impact_sensor_callback.js +21 -0
- package/dom/jsview-dom/src/engine-js/browser/view_sensor/impact_sensor_manager.js +24 -0
- package/dom/jsview-dom/src/engine-js/browser/view_sensor/index.js +9 -0
- package/dom/jsview-dom/src/engine-js/browser/view_sensor/view_sensor.js +268 -0
- package/dom/jsview-dom/src/engine-js/browser/view_sensor/view_sensor_manager.js +84 -0
- package/dom/jsview-dom/src/engine-js/browser/view_sensor/visible_sensor.js +213 -0
- package/dom/jsview-dom/src/engine-js/browser/view_store.js +41 -0
- package/dom/jsview-dom/src/engine-js/index.js +2 -0
- package/dom/jsview-dom/src/engine-js/native/README.md +1 -0
- package/dom/target_core_revision.mjs +15 -0
- package/index.js +0 -0
- package/loader/header_script_loader.js +134 -0
- package/loader/jsview-main.js +42 -0
- package/loader/jsview.config.default.js +37 -0
- package/loader/jsview.default.config.js +37 -0
- package/loader/loader.js +183 -0
- package/loader/loader_webkit.js +40 -0
- package/package.json +31 -0
- package/patches/node_modules/@vitejs/plugin-react/dist/index.cjs +520 -0
- package/patches/node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js +17609 -0
- package/patches/node_modules/@vue/compiler-sfc/dist/jsview-css-to-js.js +335 -0
- package/patches/node_modules/@vue/compiler-sfc/dist/jsview-style-format.js +446 -0
- package/patches/node_modules/@vue/compiler-sfc/dist/jsview-style-types.js +91 -0
- package/patches/node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js +8038 -0
- package/patches/node_modules/@vue/runtime-dom/dist/runtime-dom.esm-bundler.js +1700 -0
- package/patches/node_modules/postcss-js/objectifier.js +90 -0
- package/patches/node_modules/vite/dist/node/chunks/dep-0fc8e132.js +63175 -0
- package/patches/node_modules/vite/dist/node/jsview-react.vite.config.js +7 -0
- package/patches/node_modules/vite/dist/node/jsview-vue.vite.config.js +7 -0
- package/patches/node_modules/vite/dist/node/jsview.vite.config.js +56 -0
- package/patches/node_modules/vue-router/dist/vue-router.mjs +3595 -0
- package/tools/common.js +58 -0
- package/tools/jsview-jsmap-serve.js +105 -0
- package/tools/jsview-post-build.js +184 -0
- package/tools/jsview-post-install-react.js +13 -0
- package/tools/jsview-post-install-vue.js +16 -0
- package/tools/jsview-post-install.js +116 -0
- package/tools/jsview-run-android.js +67 -0
- package/tsconfig.json +34 -0
|
@@ -0,0 +1,3545 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
import Forge from "../ForgeDefine";
|
|
3
|
+
import { parseLatex, toHtml } from "./latex_parse";
|
|
4
|
+
import Velocity from "./velocity";
|
|
5
|
+
|
|
6
|
+
window.gRootView = null; // For record root view
|
|
7
|
+
Forge.sRootView = null;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @file layout_view.js
|
|
11
|
+
* @namespace Forge
|
|
12
|
+
*/
|
|
13
|
+
class TextureSetting {
|
|
14
|
+
constructor(texture, mask, texture_before_image_load, has_alpha) {
|
|
15
|
+
this.Texture = texture;
|
|
16
|
+
this._IsTextureExternal = false;
|
|
17
|
+
if (mask instanceof Forge.ImageTexture) {
|
|
18
|
+
// 重新设置请求时间
|
|
19
|
+
if (mask && mask.RenderTexture && mask.RenderTexture.NeedCheckExpired) {
|
|
20
|
+
mask.RenderTexture.RequireTime = 0;
|
|
21
|
+
}
|
|
22
|
+
this.MaskSetting = new Forge.ViewTextureMask(mask);
|
|
23
|
+
} else {
|
|
24
|
+
this.MaskSetting = mask;
|
|
25
|
+
}
|
|
26
|
+
// 重新设置请求时间
|
|
27
|
+
if (
|
|
28
|
+
texture &&
|
|
29
|
+
texture.RenderTexture &&
|
|
30
|
+
texture.RenderTexture.NeedCheckExpired
|
|
31
|
+
) {
|
|
32
|
+
texture.RenderTexture.RequireTime = 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this._IsMaskTextureExternal = false;
|
|
36
|
+
this.TextureBeforeImageLoad = texture_before_image_load;
|
|
37
|
+
this._IsPreloadImageTextureExternal = false;
|
|
38
|
+
if (typeof has_alpha === "undefined") has_alpha = true;
|
|
39
|
+
this.HasAlpha = has_alpha;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 标识这个Texture集合是否为外部Texture<br>
|
|
44
|
+
* 默认为内部Texture,内部Texture将在所附着的LayoutView从RootView移除时被强制释放<br>
|
|
45
|
+
* 文字的Texture应该用内部Texture,图形Texture一般用外部Texture
|
|
46
|
+
*
|
|
47
|
+
* @public
|
|
48
|
+
* @func SetExternal
|
|
49
|
+
* @memberof Forge.TextureSetting
|
|
50
|
+
* @instance
|
|
51
|
+
* @param {boolean} is_texture_external 主要Texture是否为外部Texture
|
|
52
|
+
* @param {boolean} is_mask_external 遮罩Texture是否为外部Texture
|
|
53
|
+
* @param {boolean} is_reload_image_external 次要Texture是否为外部Texture
|
|
54
|
+
* */
|
|
55
|
+
SetExternal(is_texture_external, is_mask_external, is_reload_image_external) {
|
|
56
|
+
this._IsTextureExternal = is_texture_external;
|
|
57
|
+
this._IsMaskTextureExternal = is_mask_external;
|
|
58
|
+
this._IsPreloadImageTextureExternal = is_reload_image_external;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
ReleaseInternalTexture(renderer, container_view) {
|
|
62
|
+
if (!this._IsTextureExternal && this.Texture) {
|
|
63
|
+
this.Texture.UnloadTex();
|
|
64
|
+
this.Texture = null;
|
|
65
|
+
}
|
|
66
|
+
if (
|
|
67
|
+
!this._IsMaskTextureExternal &&
|
|
68
|
+
this.MaskSetting /* && this.MaskSetting instanceof Forge.ImageTexture */
|
|
69
|
+
) {
|
|
70
|
+
this.MaskSetting.UnLoad();
|
|
71
|
+
this.MaskSetting = null;
|
|
72
|
+
}
|
|
73
|
+
if (!this._IsPreloadImageTextureExternal && this.TextureBeforeImageLoad) {
|
|
74
|
+
this.TextureBeforeImageLoad.UnloadTex();
|
|
75
|
+
this.TextureBeforeImageLoad = null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
DebugPrint() {
|
|
80
|
+
return ` _IsTextureExternal=${this._IsTextureExternal}`;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
Forge.TextureSetting = TextureSetting;
|
|
84
|
+
window.TextureSetting = Forge.TextureSetting; // export class;
|
|
85
|
+
|
|
86
|
+
class ExternalTextureSetting extends Forge.TextureSetting {
|
|
87
|
+
constructor(texture, mask_texture, texture_before_image_load, has_alpha) {
|
|
88
|
+
super(texture, mask_texture, texture_before_image_load, has_alpha);
|
|
89
|
+
this.SetExternal(true, true, true);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
Forge.ExternalTextureSetting = ExternalTextureSetting;
|
|
93
|
+
window.ExternalTextureSetting = Forge.ExternalTextureSetting; // export class;
|
|
94
|
+
|
|
95
|
+
class PackedLayout {
|
|
96
|
+
constructor(layout_view_base) {
|
|
97
|
+
const data_from = layout_view_base.RectInfo;
|
|
98
|
+
this.RectInfo = {
|
|
99
|
+
coordX: data_from.coordX,
|
|
100
|
+
coordY: data_from.coordY,
|
|
101
|
+
width: data_from.width,
|
|
102
|
+
height: data_from.height,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
this.LayoutParams = JSON.parse(
|
|
106
|
+
JSON.stringify(layout_view_base.LayoutParams)
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
ApplyToView(target_view) {
|
|
111
|
+
const data_from = this.RectInfo;
|
|
112
|
+
target_view.RectInfo = {
|
|
113
|
+
coordX: data_from.coordX,
|
|
114
|
+
coordY: data_from.coordY,
|
|
115
|
+
width: data_from.width,
|
|
116
|
+
height: data_from.height,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
target_view.LayoutParams = JSON.parse(JSON.stringify(this.LayoutParams));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
Forge.PackedLayout = PackedLayout;
|
|
123
|
+
|
|
124
|
+
class ViewMask {
|
|
125
|
+
constructor() {
|
|
126
|
+
this._MaskType = "COMMON";
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
Type() {
|
|
130
|
+
return this._MaskType;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
UnLoad() {
|
|
134
|
+
// need to be overrided
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
Forge.ViewMask = ViewMask;
|
|
138
|
+
|
|
139
|
+
class ViewTextureMask extends Forge.ViewMask {
|
|
140
|
+
constructor(image_texture) {
|
|
141
|
+
super();
|
|
142
|
+
this._MaskType = "TEXTURE";
|
|
143
|
+
this.ImageTexture = image_texture;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
UnLoad() {
|
|
147
|
+
this.ImageTexture.UnloadTex();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
Forge.ViewTextureMask = ViewTextureMask;
|
|
151
|
+
class ViewRoundCornerMask extends Forge.ViewMask {
|
|
152
|
+
constructor(top_left, top_right, bottom_left, bottom_right) {
|
|
153
|
+
super();
|
|
154
|
+
|
|
155
|
+
this._MaskType = "CORNER";
|
|
156
|
+
|
|
157
|
+
this._TopLeft = top_left;
|
|
158
|
+
this._TopRight = !isNaN(top_right) ? top_right : top_left;
|
|
159
|
+
this._BottomLeft = !isNaN(bottom_left) ? bottom_left : top_left;
|
|
160
|
+
this._BottomRight = !isNaN(bottom_right) ? bottom_right : top_left;
|
|
161
|
+
|
|
162
|
+
this._CornersWidth = [0.0, 0.0, 0.0, 0.0];
|
|
163
|
+
this._CornersDisable = [
|
|
164
|
+
this._TopLeft === 0 ? 1.0 : 0.0,
|
|
165
|
+
this._TopRight === 0 ? 1.0 : 0.0,
|
|
166
|
+
this._BottomLeft === 0 ? 1.0 : 0.0,
|
|
167
|
+
this._BottomRight === 0 ? 1.0 : 0.0,
|
|
168
|
+
];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
UnLoad() {
|
|
172
|
+
// nothing to do
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
Forge.ViewRoundCornerMask = ViewRoundCornerMask;
|
|
176
|
+
|
|
177
|
+
class DragSetting {
|
|
178
|
+
/**
|
|
179
|
+
* 拖拽参数设置
|
|
180
|
+
* @param {int}drag_direction 拖拽方向: 横向、纵向、自由拖拽、Disable
|
|
181
|
+
* @param {int}trigger_moved_distance onMoved事件触发的移动距离
|
|
182
|
+
* @param {boolean} enable_js_fling 是否由js进行fling操作,true:js进行fling,false:系统执行fling
|
|
183
|
+
* @param {Forge.RectArea} slide_pile 滑桩 view 滑动时由滑桩控制其滑动区域
|
|
184
|
+
* @param {int}fling_page_width 滑动页的宽度,即开启整平滑动模式
|
|
185
|
+
* @param {int}fling_page_edge 触发整屏滑动页的边界,默认为1/4
|
|
186
|
+
*/
|
|
187
|
+
constructor(
|
|
188
|
+
drag_direction,
|
|
189
|
+
trigger_moved_distance,
|
|
190
|
+
enable_js_fling,
|
|
191
|
+
slide_pile,
|
|
192
|
+
fling_page_width,
|
|
193
|
+
fling_page_edge
|
|
194
|
+
) {
|
|
195
|
+
this.DragDirection = drag_direction || 0;
|
|
196
|
+
this.TriggerMovedDistance = trigger_moved_distance || 0;
|
|
197
|
+
this._EnableJsFling = enable_js_fling ? 1 : 0;
|
|
198
|
+
this.SlidePile = slide_pile || new Forge.RectArea(0, 0, 1280, 720);
|
|
199
|
+
this.PageWidth = fling_page_width > 0 ? fling_page_width : 0xffff;
|
|
200
|
+
this.EnableTabMode = fling_page_width > 0;
|
|
201
|
+
this.PageEdge = fling_page_edge || 1 / 4;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
Forge.DragSetting = DragSetting;
|
|
206
|
+
Forge.DragSetting.DIRECTION_DISABLE = 0x00; // 只接收长按/quick tap事件
|
|
207
|
+
Forge.DragSetting.DIRECTION_VERTICAL = 0x01;
|
|
208
|
+
Forge.DragSetting.DIRECTION_HORIZONTAL = 0x02;
|
|
209
|
+
Forge.DragSetting.DIRECTION_AUTO =
|
|
210
|
+
Forge.DragSetting.DIRECTION_VERTICAL | Forge.DragSetting.DIRECTION_HORIZONTAL;
|
|
211
|
+
|
|
212
|
+
Forge.DragInfo = class {
|
|
213
|
+
constructor() {
|
|
214
|
+
this.Settings = null;
|
|
215
|
+
this.Listener = null;
|
|
216
|
+
this.ListenerFlags = 0;
|
|
217
|
+
this.OverListener = null;
|
|
218
|
+
this.OverListenerFlags = 0;
|
|
219
|
+
this.Formula = null;
|
|
220
|
+
this.SyncString = null; // Deprecated;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
SetListener(listener) {
|
|
224
|
+
this.Listener = listener;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
Forge.DragInfo.INFLEXION = 0.35; // Tension lines cross at (INFLEXION, 1)//拐点
|
|
228
|
+
|
|
229
|
+
Forge.DragInfo.DECELERATION_RATE = Math.log(0.78) / Math.log(0.9); // 减速率
|
|
230
|
+
|
|
231
|
+
Forge.DragInfo.PHYSICAL_COEF = 51890.2; // 物理系数
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* final float ppi = context.getResources().getDisplayMetrics().density * 160.0f;
|
|
235
|
+
PHYSICAL_COEF = SensorManager.GRAVITY_EARTH // g (m/s^2)
|
|
236
|
+
* 39.37f // inch/meter
|
|
237
|
+
* ppi
|
|
238
|
+
* 0.84f; // look and feel tuning
|
|
239
|
+
*/
|
|
240
|
+
Forge.DragInfo.SCROLL_FRICTION = 0.015 * 4; // 摩擦系数
|
|
241
|
+
|
|
242
|
+
Forge.DragInfo.EVENT_TYPE = {
|
|
243
|
+
OnDown: 0,
|
|
244
|
+
OnTap: 1,
|
|
245
|
+
OnLongPress: 2,
|
|
246
|
+
OnDragStart: 3,
|
|
247
|
+
OnMoved: 4,
|
|
248
|
+
OnDragEnd: 5,
|
|
249
|
+
OnRelease: 6,
|
|
250
|
+
OnFling: 7,
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
let count = 0;
|
|
254
|
+
class LayoutViewBase {
|
|
255
|
+
constructor(texture_setting, element_name) {
|
|
256
|
+
this.TextureSetting = texture_setting;
|
|
257
|
+
if (texture_setting) {
|
|
258
|
+
console.error(
|
|
259
|
+
"LayoutViewBase constructor texture_setting not undefined!"
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
this._dispatchLongPress = this._dispatchLongPress.bind(this);
|
|
263
|
+
this.Visibility = "VISIBLE";
|
|
264
|
+
this.LayoutParams = null; // TODO: 为了节省内存,将改成按需求生成
|
|
265
|
+
this.ParentView = null;
|
|
266
|
+
this.ChildViews = []; // TODO: 为了节省内存,将改成按需求生成
|
|
267
|
+
// Z-index
|
|
268
|
+
this.zIndex = 0;
|
|
269
|
+
this._Perspective = 0;
|
|
270
|
+
this._PerspectiveAnchor = [0.5, 0.5];
|
|
271
|
+
this._BackfaceVisibility = 1;
|
|
272
|
+
this._DebugCount = ++count;
|
|
273
|
+
this.childZIndexCount = 0; // 计数器,统计子界面中有多少个设置了index的界面,用于优化AddView时的z-index调整处理
|
|
274
|
+
this._IsChildOfRootView = false;
|
|
275
|
+
this._DetachFromSystemCallback = null;
|
|
276
|
+
this.Element = null;
|
|
277
|
+
this.InnerChildElement = null; // 例如video element
|
|
278
|
+
if (element_name === "root") { // react root element
|
|
279
|
+
this.Element = window.originDocument.getElementById(element_name);
|
|
280
|
+
if (!this.Element) { // vue root element
|
|
281
|
+
this.Element = window.originDocument.getElementById("app");
|
|
282
|
+
}
|
|
283
|
+
} else if (element_name === "svg" || element_name === "path") {
|
|
284
|
+
this.Element = document.createElementNS(
|
|
285
|
+
"http://www.w3.org/2000/svg",
|
|
286
|
+
element_name
|
|
287
|
+
);
|
|
288
|
+
} else if (element_name) {
|
|
289
|
+
this.Element = window.originDocument.createElement(element_name);
|
|
290
|
+
this.Element.style.position = "absolute";
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
this.TransitionStore = {}; // div的所有transition信息,多个Transition动画会同时作用?
|
|
294
|
+
|
|
295
|
+
this.TransformAnimationObj = null;
|
|
296
|
+
this._TextureAnimationObj = null;
|
|
297
|
+
|
|
298
|
+
// drag 2018/10/16(luocf), 2019/09/02(ludl)
|
|
299
|
+
this._DragInfo = null;
|
|
300
|
+
// drag 相关变量 2020/09/21
|
|
301
|
+
this.DragControl = null;
|
|
302
|
+
this._Velocity = { x: new Velocity(), y: new Velocity() };
|
|
303
|
+
this._TouchSlopSquare = 8 * 8;
|
|
304
|
+
this._InDragging = null;
|
|
305
|
+
this._InLongPress = null;
|
|
306
|
+
this._AlwaysInTapRegion = null;
|
|
307
|
+
this._LastFocusX = null;
|
|
308
|
+
this._LastFocusY = null;
|
|
309
|
+
this._DownFocusX = null;
|
|
310
|
+
this._DownFocusY = null;
|
|
311
|
+
this._LastTimeStamp = null;
|
|
312
|
+
this._ObjectFitTestCache = null;
|
|
313
|
+
|
|
314
|
+
this._ProxyView = null;
|
|
315
|
+
|
|
316
|
+
// 是否曾今挂载过rootView并拿掉了(LayoutView只能往rootView挂载一次)
|
|
317
|
+
this.Expired = false;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
Init(texture_setting) {
|
|
321
|
+
this.ResetTexture(texture_setting);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
SetElementProp(changed_props, owner_activity) {
|
|
325
|
+
if (changed_props) {
|
|
326
|
+
Object.keys(changed_props).forEach((name) => {
|
|
327
|
+
switch (name) {
|
|
328
|
+
case "jsv_enable_fade":
|
|
329
|
+
// 启动图片加载完成后的淡出处理,PC端无效
|
|
330
|
+
break;
|
|
331
|
+
case "jsv_poster_on_top":
|
|
332
|
+
// 启动海报层级提高优先级处理,PC端无效
|
|
333
|
+
break;
|
|
334
|
+
case "jsv_innerview": {
|
|
335
|
+
// 加入通过ViewStore传入的LayoutView对象
|
|
336
|
+
const view_info = Forge.sViewStore.get(changed_props[name]);
|
|
337
|
+
if (view_info) {
|
|
338
|
+
const proxy_view = view_info.view;
|
|
339
|
+
|
|
340
|
+
// 使用本view的layout作为代理view的尺寸,并重置本view尺寸信息
|
|
341
|
+
// 以此来解决dom的transition变化时,设置时位置style信息的传递问题
|
|
342
|
+
if (this.LayoutParams == null) {
|
|
343
|
+
// 避免LayoutParams为null
|
|
344
|
+
this.ResetLayoutParams({ x: 0, y: 0, width: 0, height: 0 });
|
|
345
|
+
}
|
|
346
|
+
let proxy_view_lp = this.LayoutParams;
|
|
347
|
+
this.ResetLayoutParams({ x: 0, y: 0, width: 0, height: 0 });
|
|
348
|
+
|
|
349
|
+
if (proxy_view) {
|
|
350
|
+
if (this._ProxyView === null) {
|
|
351
|
+
this._InsertProxyLayer(proxy_view, proxy_view_lp);
|
|
352
|
+
} else {
|
|
353
|
+
if (proxy_view !== this._ProxyView) {
|
|
354
|
+
console.error("Error: Can not reset proxy view");
|
|
355
|
+
} else {
|
|
356
|
+
// Do nothing
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
case "jsv_media_usetexture":
|
|
364
|
+
// Video view中使用texture展示,已经被外部处理,此处不需再处理
|
|
365
|
+
break;
|
|
366
|
+
case "jsv_text_definition":
|
|
367
|
+
// 设置本LayoutView以及所有子View中文字的清晰度,默认为1.0x,PC端无效
|
|
368
|
+
break;
|
|
369
|
+
default:
|
|
370
|
+
Forge.LogE(`Error: View Unknown prop name=${name}`);
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
InsertView(child_view, child_view_in_list, layout_params, packed_layout) {
|
|
378
|
+
this._InsertView(child_view, child_view_in_list, layout_params, packed_layout);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
AddView(child_view, layout_params, packed_layout) {
|
|
382
|
+
this._InsertView(child_view, null, layout_params, packed_layout);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
MoveChildView(child_view_to_move, target_parent, child_view_in_list) {
|
|
386
|
+
if (this._ProxyView != null && child_view_to_move != this._ProxyView) {
|
|
387
|
+
// 所有的 MoveChildView 操作被ProxyView代理
|
|
388
|
+
this._ProxyView.MoveChildView(child_view_to_move, target_parent);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// 从原节点拿掉
|
|
393
|
+
let found = false;
|
|
394
|
+
for (var i = 0; i < this.ChildViews.length; i++) {
|
|
395
|
+
if (this.ChildViews[i] == child_view_to_move) {
|
|
396
|
+
if (child_view_to_move.zIndex != 0)
|
|
397
|
+
this.childZIndexCount--;
|
|
398
|
+
this.ChildViews.splice(i, 1);
|
|
399
|
+
child_view_to_move.ParentView = null;
|
|
400
|
+
found = true;
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (!found) {
|
|
405
|
+
Forge.LogE("MoveChildView(): view is not in child list" + " stack=");
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// 移动到新节点中
|
|
409
|
+
target_parent._InsertView(child_view_to_move, child_view_in_list, child_view_to_move.LayoutParams);
|
|
410
|
+
|
|
411
|
+
// 执行HTML的element移动操作,移动后原父节点会自动删除
|
|
412
|
+
let behind_view = null;
|
|
413
|
+
if (child_view_in_list) {
|
|
414
|
+
behind_view = target_parent.ChildViews[target_parent.ChildViews.indexOf(child_view_in_list) + 1];
|
|
415
|
+
}
|
|
416
|
+
if (behind_view && target_parent.Element.contains(behind_view.Element)) {
|
|
417
|
+
target_parent.Element.insertBefore(child_view_to_move.Element, behind_view.Element);
|
|
418
|
+
} else {
|
|
419
|
+
target_parent.Element.appendChild(child_view_to_move.Element);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
_InsertView(child_view, child_view_in_list, layout_params, packed_layout) {
|
|
424
|
+
if (layout_params) {
|
|
425
|
+
if (!(layout_params instanceof Forge.LayoutParamsBase)) {
|
|
426
|
+
child_view.LayoutParams = new Forge.LayoutParams(layout_params);
|
|
427
|
+
} else {
|
|
428
|
+
child_view.LayoutParams = layout_params.Clone();
|
|
429
|
+
}
|
|
430
|
+
} else {
|
|
431
|
+
if (!child_view.LayoutParams) {
|
|
432
|
+
child_view.LayoutParams = new Forge.LayoutParams({ x: 0, y: 0 });
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (child_view.LayoutParams !== null) {
|
|
437
|
+
if (child_view.LayoutParams.MarginLeft) {
|
|
438
|
+
child_view.Element.style.left = `${child_view.LayoutParams.MarginLeft}px`;
|
|
439
|
+
}
|
|
440
|
+
if (child_view.LayoutParams.MarginTop) {
|
|
441
|
+
child_view.Element.style.top = `${child_view.LayoutParams.MarginTop}px`;
|
|
442
|
+
}
|
|
443
|
+
if (child_view.LayoutParams.Width) {
|
|
444
|
+
child_view.Element.style.width = `${child_view.LayoutParams.Width}px`;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (child_view.LayoutParams.Height) {
|
|
448
|
+
child_view.Element.style.height = `${child_view.LayoutParams.Height}px`;
|
|
449
|
+
} else {
|
|
450
|
+
child_view.Element.style.height = "";
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
child_view.ParentView = this;
|
|
455
|
+
if (child_view_in_list) {
|
|
456
|
+
// 插入模式(插到目标view之前)
|
|
457
|
+
let found_idx = this.ChildViews.indexOf(child_view_in_list);
|
|
458
|
+
if (found_idx < 0) {
|
|
459
|
+
found_idx = this.ChildViews.length; // 默认追加到最后
|
|
460
|
+
}
|
|
461
|
+
this.ChildViews.splice(found_idx, 0, child_view);
|
|
462
|
+
} else {
|
|
463
|
+
// 非插入形式
|
|
464
|
+
this.ChildViews.push(child_view);
|
|
465
|
+
}
|
|
466
|
+
this._ChildrenListDirty = true;
|
|
467
|
+
|
|
468
|
+
if (this._IsChildOfRootView) {
|
|
469
|
+
child_view._OnAttachToSystem();
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
SetZIndex(z_index) {
|
|
474
|
+
this.Element.style.zIndex = z_index;
|
|
475
|
+
this.zIndex = z_index;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Perspective距离<br>
|
|
480
|
+
*
|
|
481
|
+
* hide public
|
|
482
|
+
* @func SetPerspective
|
|
483
|
+
* @memberof Forge.LayoutViewBase
|
|
484
|
+
* @instance
|
|
485
|
+
* @param {int} distance 观察点距离view的值, 最大为2^16 - 1
|
|
486
|
+
* */
|
|
487
|
+
SetPerspective(distance, origin) {
|
|
488
|
+
this.Element.style.perspective = `${distance}px`;
|
|
489
|
+
this.Element.style.webkitPerspective = `${distance}px`;
|
|
490
|
+
this.Element.style.perspectiveOrigin = origin;
|
|
491
|
+
this.Element.style.webkitPerspectiveOrigin = origin;
|
|
492
|
+
this._Perspective = distance;
|
|
493
|
+
this._PerspectiveOrigin = origin;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* 背面是否可见<br>
|
|
498
|
+
*
|
|
499
|
+
* hide public
|
|
500
|
+
* @func SetBackfaceVisibility
|
|
501
|
+
* @memberof Forge.LayoutViewBase
|
|
502
|
+
* @instance
|
|
503
|
+
* @param {boolean} visible 可见性
|
|
504
|
+
* */
|
|
505
|
+
SetBackfaceVisibility(visible) {
|
|
506
|
+
console.log("set back face", visible);
|
|
507
|
+
this.Element.style.backfaceVisibility = visible ? "visible" : "hidden";
|
|
508
|
+
this.Element.style.webkitBackfaceVisibility = visible
|
|
509
|
+
? "visible"
|
|
510
|
+
: "hidden";
|
|
511
|
+
console.log(`back face style ${this.Element.style.backfaceVisibility}`);
|
|
512
|
+
this._BackfaceVisibility = visible ? 1 : 0;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
SetTransformStyle(transform_style) {
|
|
516
|
+
this.Element.style.transformStyle = transform_style;
|
|
517
|
+
this.Element.style.webkitTransformStyle = transform_style;
|
|
518
|
+
this._TransformStyle = transform_style;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
EnableDivTouch(ele, setting) {
|
|
522
|
+
if (ele.eventHandlers && ele.eventHandlers.onClick) {
|
|
523
|
+
this.Element.onclick = (ev) => {
|
|
524
|
+
ele.eventHandlers.onClick();
|
|
525
|
+
if (ev.preventDefault) {
|
|
526
|
+
ev.preventDefault();
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
this.Element.style.pointerEvents = "auto";
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
_DoDragPause(event) {
|
|
534
|
+
if (this._DragInfo.Settings.EnableTabMode) {
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
if (this.DragControl) {
|
|
538
|
+
this.DragControl.pause((view_x, view_y) => {
|
|
539
|
+
if (this.Element.style.transform !== null) {
|
|
540
|
+
// 对view_x, view_y进行校对
|
|
541
|
+
let lp = this.GetLayoutParams();
|
|
542
|
+
lp = this._GetMovedLayoutParams(
|
|
543
|
+
view_x - lp.MarginLeft,
|
|
544
|
+
view_y - lp.MarginTop
|
|
545
|
+
);
|
|
546
|
+
this.ResetLayoutParams(lp);
|
|
547
|
+
this._DragImactSensorRecycle();
|
|
548
|
+
console.log(
|
|
549
|
+
`_DoDragPause lp.MarginLeft:${lp.MarginLeft}, lp.MarginTop:${lp.MarginTop}`
|
|
550
|
+
);
|
|
551
|
+
this.DragControl = null;
|
|
552
|
+
this.Element.style.transform = null;
|
|
553
|
+
// 补充event
|
|
554
|
+
event.viewX = view_x;
|
|
555
|
+
event.viewY = view_y;
|
|
556
|
+
|
|
557
|
+
this._DragInfo.Listener.OnFling(event);
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
TouchEventProcess(event) {
|
|
564
|
+
// 将event type转换为字符串
|
|
565
|
+
let event_used = false;
|
|
566
|
+
switch (event.type) {
|
|
567
|
+
case Forge.DragInfo.EVENT_TYPE.OnDown: {
|
|
568
|
+
console.log("TouchEventProcess OnDown in");
|
|
569
|
+
this._DoDragPause(event);
|
|
570
|
+
if (this._DragInfo.Listener && this._DragInfo.Listener.OnDown) {
|
|
571
|
+
event_used = this._DragInfo.Listener.OnDown(event);
|
|
572
|
+
}
|
|
573
|
+
break;
|
|
574
|
+
}
|
|
575
|
+
case Forge.DragInfo.EVENT_TYPE.OnTap:
|
|
576
|
+
if (this._DragInfo.Listener && this._DragInfo.Listener.OnTap) {
|
|
577
|
+
event_used = this._DragInfo.Listener.OnTap(event);
|
|
578
|
+
}
|
|
579
|
+
break;
|
|
580
|
+
case Forge.DragInfo.EVENT_TYPE.OnLongPress:
|
|
581
|
+
if (this._DragInfo.Listener && this._DragInfo.Listener.OnLongPress) {
|
|
582
|
+
event_used = this._DragInfo.Listener.OnLongPress(event);
|
|
583
|
+
}
|
|
584
|
+
break;
|
|
585
|
+
case Forge.DragInfo.EVENT_TYPE.OnDragStart:
|
|
586
|
+
this._DragMovedDistanceX = 0;
|
|
587
|
+
this._DragMovedDistanceY = 0;
|
|
588
|
+
if (this._DragInfo.Listener && this._DragInfo.Listener.OnDragStart) {
|
|
589
|
+
event_used = this._DragInfo.Listener.OnDragStart(event);
|
|
590
|
+
}
|
|
591
|
+
break;
|
|
592
|
+
case Forge.DragInfo.EVENT_TYPE.OnMoved:
|
|
593
|
+
if (this._DragInfo.Listener && this._DragInfo.Listener.OnMoved) {
|
|
594
|
+
event_used = this._DoDragMove(event, true);
|
|
595
|
+
}
|
|
596
|
+
break;
|
|
597
|
+
case Forge.DragInfo.EVENT_TYPE.OnDragEnd:
|
|
598
|
+
if (this._DragInfo.Listener && this._DragInfo.Listener.OnDragEnd) {
|
|
599
|
+
// 对应吸附性,进行动画调整
|
|
600
|
+
const enable_tab_mode = this._SlideIfEnableTabMod(event, -1);
|
|
601
|
+
if (enable_tab_mode) {
|
|
602
|
+
event_used = true;
|
|
603
|
+
} else {
|
|
604
|
+
event_used = this._DoDragEnd(event);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
break;
|
|
608
|
+
case Forge.DragInfo.EVENT_TYPE.OnRelease:
|
|
609
|
+
if (this._DragInfo.Listener && this._DragInfo.Listener.OnRelease) {
|
|
610
|
+
event_used = this._DragInfo.Listener.OnRelease(event);
|
|
611
|
+
}
|
|
612
|
+
break;
|
|
613
|
+
case Forge.DragInfo.EVENT_TYPE.OnFling:
|
|
614
|
+
if (this._DragInfo.Listener && this._DragInfo.Listener.OnFling) {
|
|
615
|
+
const enable_tab_mode = this._SlideIfEnableTabMod(event, -1);
|
|
616
|
+
if (enable_tab_mode) {
|
|
617
|
+
event_used = true;
|
|
618
|
+
} else {
|
|
619
|
+
event_used = this._DoFling(event);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
break;
|
|
623
|
+
default:
|
|
624
|
+
console.log(`TouchEventProcess:${event}`);
|
|
625
|
+
break;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
return event_used;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* 使Drag无效
|
|
633
|
+
* @constructor
|
|
634
|
+
*/
|
|
635
|
+
DisableDrag() {
|
|
636
|
+
this._DragInfo = null;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* 使能拖拽
|
|
641
|
+
* @param {Forge.DragSetting} setting 拖拽设置
|
|
642
|
+
* @param {Object} listener 拖拽事件 listener Event事件:
|
|
643
|
+
* OnDragEnd:{viewX:0,viewY:0},
|
|
644
|
+
* OnMoved:{deltaX:0,deltaY:0},
|
|
645
|
+
* Other:{x:0,y:0}//点击位置,相对于屏幕的绝对坐标
|
|
646
|
+
* @param {String} movement_formula 移动公式
|
|
647
|
+
* @constructor
|
|
648
|
+
*/
|
|
649
|
+
EnableDrag(setting, listener, movement_formula) {
|
|
650
|
+
if (!(setting instanceof Forge.DragSetting)) {
|
|
651
|
+
Forge.ThrowError("EnableDrag The setting is not Forge.DragSetting");
|
|
652
|
+
}
|
|
653
|
+
if (listener === null) {
|
|
654
|
+
Forge.ThrowError("EnableDrag The listener is null");
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
const drag_info = new Forge.DragInfo();
|
|
658
|
+
drag_info.Settings = setting;
|
|
659
|
+
drag_info.SetListener(listener);
|
|
660
|
+
drag_info.Formula = movement_formula;
|
|
661
|
+
this._DragInfo = drag_info;
|
|
662
|
+
this.DragControl = null;
|
|
663
|
+
|
|
664
|
+
// 追加事件监听
|
|
665
|
+
this._AddEventListener();
|
|
666
|
+
Forge.sRenderBridge.RequestSwap();
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
RemoveView(child_view_to_remove) {
|
|
670
|
+
for (let i = 0; i < this.ChildViews.length; i++) {
|
|
671
|
+
if (this.ChildViews[i] === child_view_to_remove) {
|
|
672
|
+
if (child_view_to_remove.IsChildOfRootView()) {
|
|
673
|
+
child_view_to_remove._OnDetachFromSystem();
|
|
674
|
+
}
|
|
675
|
+
this.ChildViews.splice(i, 1);
|
|
676
|
+
child_view_to_remove.ParentView = null;
|
|
677
|
+
break;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
_OnDetachFromSystem() {
|
|
683
|
+
this._IsChildOfRootView = false;
|
|
684
|
+
if (this._DetachFromSystemCallback) {
|
|
685
|
+
this._DetachFromSystemCallback.some((o, i, arr) => {
|
|
686
|
+
o();
|
|
687
|
+
});
|
|
688
|
+
this._DetachFromSystemCallback = null; // 执行完毕要清理
|
|
689
|
+
} else {
|
|
690
|
+
this.OnDettachFromSystem();
|
|
691
|
+
}
|
|
692
|
+
for (let i = 0; i < this.ChildViews.length; i++) {
|
|
693
|
+
const child_view = this.ChildViews[i];
|
|
694
|
+
child_view._OnDetachFromSystem();
|
|
695
|
+
}
|
|
696
|
+
this.ParentView.Element.removeChild(this.Element);
|
|
697
|
+
|
|
698
|
+
this._releaseViewResources();
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
RegisterDetachCallback(callback) {
|
|
702
|
+
if (callback) {
|
|
703
|
+
if (this._DetachFromSystemCallback == null) {
|
|
704
|
+
this._DetachFromSystemCallback = [];
|
|
705
|
+
}
|
|
706
|
+
this._DetachFromSystemCallback.push(callback);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
UnregisterDetachCallback(callback) {
|
|
711
|
+
if (callback && this._DetachFromSystemCallback) {
|
|
712
|
+
let found = false;
|
|
713
|
+
let arr = this._DetachFromSystemCallback;
|
|
714
|
+
for (let i = 0; i < arr.length; i++) {
|
|
715
|
+
if (arr[i] === callback) {
|
|
716
|
+
arr.splice(i, 1);
|
|
717
|
+
found = true;
|
|
718
|
+
break;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
if (!found) {
|
|
722
|
+
console.error("no found");
|
|
723
|
+
} else {
|
|
724
|
+
if (arr.length == 0) {
|
|
725
|
+
this._DetachFromSystemCallback = null; // 清理内存
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
} else {
|
|
729
|
+
console.error("Unregister nothing...");
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
/**
|
|
734
|
+
* 按需重载的回调函数
|
|
735
|
+
*
|
|
736
|
+
* @public
|
|
737
|
+
* @func OnDettachFromSystem
|
|
738
|
+
* @memberof Forge.LayoutViewBase
|
|
739
|
+
* @instance
|
|
740
|
+
* */
|
|
741
|
+
OnDettachFromSystem() {
|
|
742
|
+
// Override if needed
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
_releaseViewResources() {
|
|
746
|
+
if (!this.Expired) {
|
|
747
|
+
// Stop animation
|
|
748
|
+
this.StopAnimation();
|
|
749
|
+
this.StopTextureAnimation();
|
|
750
|
+
this.Expired = true;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
ClearViews() {
|
|
755
|
+
const child_count = this.ChildViews.length;
|
|
756
|
+
if (child_count === 0) {
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
for (let i = 0; i < child_count; i++) {
|
|
760
|
+
const child_view = this.ChildViews[i];
|
|
761
|
+
if (child_view && child_view.IsChildOfRootView()) {
|
|
762
|
+
child_view._OnDetachFromSystem();
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
this.ChildViews = [];
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
_ResetTextStyle(resource_info) {
|
|
770
|
+
this.Element.style.overflow = "hidden";
|
|
771
|
+
|
|
772
|
+
// Get all style from id
|
|
773
|
+
// display style
|
|
774
|
+
let ds_describe = Forge.sTextStyleCache.GetDsFromId(
|
|
775
|
+
resource_info.Set.IDS.DS
|
|
776
|
+
).Describe;
|
|
777
|
+
// font style
|
|
778
|
+
let fs_describe = Forge.sTextStyleCache.GetFsFromId(
|
|
779
|
+
resource_info.Set.IDS.FS
|
|
780
|
+
).Describe;
|
|
781
|
+
// color style
|
|
782
|
+
let cs_describe = Forge.sTextStyleCache.GetCsFromId(
|
|
783
|
+
resource_info.Set.IDS.CS
|
|
784
|
+
).Describe;
|
|
785
|
+
// special style
|
|
786
|
+
let ss_describe = null;
|
|
787
|
+
if (resource_info.Set.IDS.SS !== "DISABLE") {
|
|
788
|
+
ss_describe = Forge.sTextStyleCache.GetSsFromId(
|
|
789
|
+
resource_info.Set.IDS.SS
|
|
790
|
+
).Describe;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// font
|
|
794
|
+
this.Element.style.fontFamily = fs_describe.font;
|
|
795
|
+
this.Element.style.fontSize = `${resource_info.Set.FS}px`;
|
|
796
|
+
if (fs_describe.italic) {
|
|
797
|
+
this.Element.style.fontStyle = "italic";
|
|
798
|
+
}
|
|
799
|
+
if (fs_describe.bold) {
|
|
800
|
+
this.Element.style.fontWeight = "bold";
|
|
801
|
+
} else {
|
|
802
|
+
this.Element.style.fontWeight = "normal";
|
|
803
|
+
}
|
|
804
|
+
this.Element.style.textOverflow = ds_describe.text_overflow;
|
|
805
|
+
this.Element.style.wordBreak = "normal";
|
|
806
|
+
|
|
807
|
+
// word wrap
|
|
808
|
+
let word_wrap = ds_describe.word_wrap;
|
|
809
|
+
if (word_wrap === "none") {
|
|
810
|
+
this.Element.style.whiteSpace = "nowrap";
|
|
811
|
+
} else if (word_wrap) {
|
|
812
|
+
this.Element.style.wordWrap = word_wrap.replace("_", "-");
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
// align
|
|
816
|
+
this.Element.style.textAlign = ds_describe.alignment;
|
|
817
|
+
this.Element.style.verticalAlign = ds_describe.vertical_area_align; // 配合高阶控件区域居中设置
|
|
818
|
+
|
|
819
|
+
//direction
|
|
820
|
+
this.Element.style.direction = ds_describe.direction;
|
|
821
|
+
|
|
822
|
+
// color
|
|
823
|
+
let text_color = cs_describe.text_color;
|
|
824
|
+
if (text_color.startsWith("#") && text_color.length === 9) {
|
|
825
|
+
// #AARRGGBB -> #RRGGBB
|
|
826
|
+
text_color = "#" + text_color.substr(3, 6);
|
|
827
|
+
}
|
|
828
|
+
this.Element.style.color = text_color;
|
|
829
|
+
let bg_color = cs_describe.bg_color;
|
|
830
|
+
let opacity = false;
|
|
831
|
+
if (bg_color.startsWith("#") && bg_color.length === 9) {
|
|
832
|
+
// #AARRGGBB -> #RRGGBB
|
|
833
|
+
opacity = bg_color.startsWith("#00");
|
|
834
|
+
bg_color = "#" + bg_color.substr(3, 6);
|
|
835
|
+
}
|
|
836
|
+
if (!opacity) {
|
|
837
|
+
this.Element.style.backgroundColor = bg_color;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
if (ss_describe) {
|
|
841
|
+
// Text shadow
|
|
842
|
+
if (ss_describe.shadow_blur > 0) {
|
|
843
|
+
this.Element.style.textShadow = `${ss_describe.shadow_offset_x}px ${ss_describe.shadow_offset_y}px ${ss_describe.shadow_blur}px ${ss_describe.shadow_color}`
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// Text stroke
|
|
847
|
+
if (ss_describe.stroke_width > 0) {
|
|
848
|
+
this.Element.style.WebkitTextStroke = `${ss_describe.stroke_width}px ${ss_describe.stroke_color}`;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// 显示width x height
|
|
853
|
+
this.Element.style.width = `${resource_info.Set.W}px`;
|
|
854
|
+
this.Element.style.height = `${resource_info.Set.H}px`;
|
|
855
|
+
|
|
856
|
+
// line height
|
|
857
|
+
if (resource_info.Set.LH) {
|
|
858
|
+
this.Element.style.lineHeight = `${resource_info.Set.LH}px`;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
if (resource_info.Set.EA) {
|
|
862
|
+
let emptyRect = resource_info.Set.EA;
|
|
863
|
+
let div = window.originDocument.createElement("div");
|
|
864
|
+
div.style.float = emptyRect.x > 0 ? "right" : "left";
|
|
865
|
+
div.style.width = emptyRect.w + "px";
|
|
866
|
+
// -1, 是因为网页端会多影响一行
|
|
867
|
+
div.style.height = emptyRect.h - 1 + "px";
|
|
868
|
+
div.style.backgroundColor = "rgba(0,0,0,0)";
|
|
869
|
+
div.style.position = "relative";
|
|
870
|
+
this.Element.appendChild(div);
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
if (resource_info.Set.LA) {
|
|
874
|
+
// latex文本
|
|
875
|
+
const node_info = parseLatex(resource_info.Set.ST);
|
|
876
|
+
toHtml(this.Element, node_info);
|
|
877
|
+
} else {
|
|
878
|
+
let textDiv = window.originDocument.createElement("span");
|
|
879
|
+
textDiv.textContent = resource_info.Set.ST;
|
|
880
|
+
this.Element.appendChild(textDiv);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
_SetBorderRadius(mask_setting) {
|
|
885
|
+
const target_element = this.InnerChildElement
|
|
886
|
+
? this.InnerChildElement
|
|
887
|
+
: this.Element;
|
|
888
|
+
target_element.style.borderRadius = `${mask_setting._TopLeft}px ${mask_setting._TopRight}px ${mask_setting._BottomRight}px ${mask_setting._BottomLeft}px`;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// 将本View的所有子节点都移动到Proxy层中
|
|
892
|
+
_InsertProxyLayer(proxy_view, layout_params) {
|
|
893
|
+
proxy_view.ParentView = this;
|
|
894
|
+
|
|
895
|
+
// ParentView绑定后, 执行Proxy View 往RootView上的绑定操作
|
|
896
|
+
if (this._IsChildOfRootView) {
|
|
897
|
+
// 步骤1: 当前view所有子 depth + 1(因为插入了新层次proxyView)
|
|
898
|
+
for (let children_view of this.ChildViews) {
|
|
899
|
+
children_view._AdvanceDepthForProxyLayer();
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// 步骤2: proxy加入rootView树中
|
|
903
|
+
proxy_view._OnAttachToSystem();
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// 将此View Child合并到proxyView的Child中
|
|
907
|
+
proxy_view.ChildViews = proxy_view.ChildViews.concat(this.ChildViews);
|
|
908
|
+
proxy_view._ChildrenListDirty = true;
|
|
909
|
+
for (let i = 0; i < proxy_view.ChildViews.length; i++) {
|
|
910
|
+
proxy_view.ChildViews[i].ParentView = proxy_view;
|
|
911
|
+
proxy_view._RequestLayoutForAddingView(proxy_view.ChildViews[i]);
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
// 应用Layout params
|
|
915
|
+
if (layout_params !== null) {
|
|
916
|
+
if (!(layout_params instanceof Forge.LayoutParamsBase)) {
|
|
917
|
+
proxy_view.LayoutParams = new Forge.LayoutParams(layout_params);
|
|
918
|
+
} else {
|
|
919
|
+
proxy_view.LayoutParams = layout_params.Clone();
|
|
920
|
+
}
|
|
921
|
+
} else {
|
|
922
|
+
if (proxy_view.LayoutParams === null) {
|
|
923
|
+
proxy_view.LayoutParams = new Forge.LayoutParams({ x: 0, y: 0 });
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
// 设置element 属性
|
|
927
|
+
proxy_view.ResetLayoutParams(proxy_view.LayoutParams);
|
|
928
|
+
|
|
929
|
+
// 重置原节点的ChildViews
|
|
930
|
+
this.ChildViews = [proxy_view];
|
|
931
|
+
this._ChildrenListDirty = true;
|
|
932
|
+
this._RequestLayoutForAddingView(proxy_view);
|
|
933
|
+
|
|
934
|
+
// 关联ProxyView
|
|
935
|
+
this._ProxyView = proxy_view;
|
|
936
|
+
// Poster on top关系不需要重建
|
|
937
|
+
|
|
938
|
+
// 将子view追加到父view上
|
|
939
|
+
if (this._IsChildOfRootView) {
|
|
940
|
+
proxy_view._OnAttachToSystem();
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
_RequestLayoutForAddingView(child_view) {
|
|
945
|
+
this._RequestLayout();
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
/**
|
|
949
|
+
* 设置新的Texture集合
|
|
950
|
+
*
|
|
951
|
+
* @public
|
|
952
|
+
* @func ResetTexture
|
|
953
|
+
* @memberof Forge.LayoutViewBase
|
|
954
|
+
* @instance
|
|
955
|
+
* @param {Forge.TextureSetting} texture_setting 新的Texture集合
|
|
956
|
+
* */
|
|
957
|
+
ResetTexture(texture_setting) {
|
|
958
|
+
this.TextureSetting = texture_setting;
|
|
959
|
+
if (texture_setting) {
|
|
960
|
+
if (texture_setting.Texture.Source) {
|
|
961
|
+
if (this.Element.tagName === "IMG") {
|
|
962
|
+
// 图片元素,设置url到src中
|
|
963
|
+
this.Element.src = texture_setting.Texture.Source;
|
|
964
|
+
} else {
|
|
965
|
+
this.Element.style.backgroundImage = `url(${texture_setting.Texture.Source})`;
|
|
966
|
+
this.Element.style.backgroundSize = "100% 100%";
|
|
967
|
+
}
|
|
968
|
+
} else if (texture_setting.Texture.Gradient) {
|
|
969
|
+
this.Element.style.backgroundImage = texture_setting.Texture.Gradient;
|
|
970
|
+
} else if (
|
|
971
|
+
texture_setting.Texture.RenderTexture &&
|
|
972
|
+
texture_setting.Texture.RenderTexture._SyncingResourceInfo
|
|
973
|
+
) {
|
|
974
|
+
const render_texture = texture_setting.Texture.RenderTexture;
|
|
975
|
+
const resource_info = render_texture._SyncingResourceInfo;
|
|
976
|
+
if (resource_info.Nam === "TST") {
|
|
977
|
+
this._ResetTextStyle(resource_info);
|
|
978
|
+
} else if (resource_info.Nam === "CT") {
|
|
979
|
+
this.Element.style.backgroundColor = resource_info.Set.Clr;
|
|
980
|
+
} else if (resource_info.Nam === "VPLY") {
|
|
981
|
+
const video_el = resource_info.Set.Hdl;
|
|
982
|
+
|
|
983
|
+
// 在Forge html状态,video的显示尺寸由父元素决定
|
|
984
|
+
video_el.style.width = "100%";
|
|
985
|
+
video_el.style.height = "100%";
|
|
986
|
+
video_el.style.objectFit = "fill";
|
|
987
|
+
|
|
988
|
+
this.Element.appendChild(video_el);
|
|
989
|
+
this.InnerChildElement = video_el;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
if (texture_setting.MaskSetting) {
|
|
994
|
+
if (texture_setting.MaskSetting._MaskType === "CORNER") {
|
|
995
|
+
this._SetBorderRadius(texture_setting.MaskSetting);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
} else {
|
|
999
|
+
this.Element.style.backgroundColor = ""
|
|
1000
|
+
this.Element.style.backgroundImage = "";
|
|
1001
|
+
this.Element.style.borderRadius = "";
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
SetVisibility(new_visibility) {
|
|
1006
|
+
if (typeof new_visibility === "string") {
|
|
1007
|
+
this.Element.style.visibility = new_visibility.toLocaleLowerCase();
|
|
1008
|
+
} else {
|
|
1009
|
+
this.Element.style.visibility = "inherit";
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
_OnAttachToSystem() {
|
|
1014
|
+
if (this.Element.id === "svg" || this.Element.id === "path") {
|
|
1015
|
+
console.log("_OnAttachToSystem appendChild");
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
// 进行Element插入操作
|
|
1019
|
+
let behind_view = this.ParentView.ChildViews[this.ParentView.ChildViews.indexOf(this) + 1];
|
|
1020
|
+
if (behind_view && this.ParentView.Element.contains(behind_view.Element)) {
|
|
1021
|
+
this.ParentView.Element.insertBefore(this.Element, behind_view.Element);
|
|
1022
|
+
} else {
|
|
1023
|
+
this.ParentView.Element.appendChild(this.Element);
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
this._IsChildOfRootView = true;
|
|
1027
|
+
const child_view_list = this.ChildViews;
|
|
1028
|
+
let child_view;
|
|
1029
|
+
for (let i = 0; i < child_view_list.length; i++) {
|
|
1030
|
+
child_view = child_view_list[i];
|
|
1031
|
+
child_view._OnAttachToSystem();
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
IsChildOfRootView() {
|
|
1036
|
+
return this._IsChildOfRootView;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
StartAnimation(anim, anim_for_self, delay) {
|
|
1040
|
+
if (
|
|
1041
|
+
typeof this.TransformAnimationObj !== "undefined" &&
|
|
1042
|
+
this.TransformAnimationObj
|
|
1043
|
+
) {
|
|
1044
|
+
this.TransformAnimationObj.Cancel(anim);
|
|
1045
|
+
this.TransformAnimationObj = null;
|
|
1046
|
+
if (!window.jsvInAndroidWebView) {
|
|
1047
|
+
this.Element.style.animation = null;
|
|
1048
|
+
} else {
|
|
1049
|
+
this.Element.style.webkitAnimation = null;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
// 动画事件转发给proxyView,本体不做,用于解决inner-view的css-transition和css-animation不容易设置的问题
|
|
1054
|
+
// 注意点:放在Animation cancel之后,以防本view有原始动画(不过理论上不会有)
|
|
1055
|
+
if (this._ProxyView != null) {
|
|
1056
|
+
this._ProxyView.StartAnimation(anim, anim_for_self, delay);
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
this.TransformAnimationObj = anim;
|
|
1061
|
+
if (!isNaN(delay) && delay > 0) {
|
|
1062
|
+
anim.EnableDelay(delay);
|
|
1063
|
+
}
|
|
1064
|
+
anim.Start(this);
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
ApplyStyleTransition(new_map) {
|
|
1068
|
+
this.TransitionStore = { ...this.TransitionStore, ...new_map };
|
|
1069
|
+
let transitions = "";
|
|
1070
|
+
Object.values(this.TransitionStore).forEach((value) => {
|
|
1071
|
+
if (transitions) {
|
|
1072
|
+
transitions += ",";
|
|
1073
|
+
}
|
|
1074
|
+
transitions += value;
|
|
1075
|
+
});
|
|
1076
|
+
if (!window.jsvInAndroidWebView) {
|
|
1077
|
+
this.Element.style.transition = transitions;
|
|
1078
|
+
} else {
|
|
1079
|
+
this.Element.style.webkitTransition = transitions;
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
/**
|
|
1084
|
+
* 停止这个LayoutView的动画变换,并重置曾经进行动画变换的矩阵
|
|
1085
|
+
*
|
|
1086
|
+
* @public
|
|
1087
|
+
* @func StopAnimation
|
|
1088
|
+
* @memberof Forge.LayoutViewBase
|
|
1089
|
+
* @instance
|
|
1090
|
+
* */
|
|
1091
|
+
StopAnimation() {
|
|
1092
|
+
if (
|
|
1093
|
+
typeof this.TransformAnimationObj !== "undefined" &&
|
|
1094
|
+
this.TransformAnimationObj
|
|
1095
|
+
) {
|
|
1096
|
+
this.TransformAnimationObj.Cancel();
|
|
1097
|
+
this.TransformAnimationObj = null;
|
|
1098
|
+
// 状态将在Animation触发的DetachAnimation中恢复,不需要在此手动恢复
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
// 动画事件转发给proxyView,本体不做,用于解决inner-view的css-transition和css-animation不容易设置的问题
|
|
1102
|
+
// 注意点:放在Animation cancel之后,以防本view有原始动画(不过理论上不会有)
|
|
1103
|
+
if (this._ProxyView != null) {
|
|
1104
|
+
this._ProxyView.StopAnimation();
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
/**
|
|
1110
|
+
* 对这个LayoutView开始进行Texture动画变换(相对于view自身)
|
|
1111
|
+
*
|
|
1112
|
+
* @public
|
|
1113
|
+
* @func StartTextureAnimation
|
|
1114
|
+
* @memberof Forge.LayoutViewBase
|
|
1115
|
+
* @instance
|
|
1116
|
+
* @param {Forge.AnimationBase} anim 动画设置,例如通过new Forge.TranslateAnimation()创建
|
|
1117
|
+
* */
|
|
1118
|
+
StartTextureAnimation(anim) {
|
|
1119
|
+
if (
|
|
1120
|
+
typeof this._TextureAnimationObj !== "undefined" &&
|
|
1121
|
+
this._TextureAnimationObj
|
|
1122
|
+
) {
|
|
1123
|
+
this._TextureAnimationObj.Cancel(anim);
|
|
1124
|
+
this._TextureAnimationObj = null;
|
|
1125
|
+
}
|
|
1126
|
+
this._TextureAnimationObj = anim;
|
|
1127
|
+
anim.AsTextureAnimation();
|
|
1128
|
+
anim.Start(this);
|
|
1129
|
+
this._RequestLayout();
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
_RequestLayout() { }
|
|
1133
|
+
|
|
1134
|
+
/**
|
|
1135
|
+
* 停止这个LayoutView中的Texture的动画变换,并重置曾经进行动画变换的矩阵
|
|
1136
|
+
*
|
|
1137
|
+
* @public
|
|
1138
|
+
* @func StopAnimation
|
|
1139
|
+
* @memberof Forge.LayoutViewBase
|
|
1140
|
+
* @instance
|
|
1141
|
+
* */
|
|
1142
|
+
StopTextureAnimation() {
|
|
1143
|
+
if (
|
|
1144
|
+
typeof this._TextureAnimationObj !== "undefined" &&
|
|
1145
|
+
this._TextureAnimationObj
|
|
1146
|
+
) {
|
|
1147
|
+
this._TextureAnimationObj.Cancel();
|
|
1148
|
+
this._TextureAnimationObj = null;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
/**
|
|
1153
|
+
* 停止该LayoutView和其所有子LayoutView的动画,并重置曾经进行动画变换的矩阵
|
|
1154
|
+
*
|
|
1155
|
+
* @public
|
|
1156
|
+
* @func StopAllAnimations
|
|
1157
|
+
* @memberof Forge.LayoutViewBase
|
|
1158
|
+
* @instance
|
|
1159
|
+
* */
|
|
1160
|
+
StopAllAnimations() {
|
|
1161
|
+
this.StopAnimation();
|
|
1162
|
+
this.StopTextureAnimation();
|
|
1163
|
+
for (let i = 0; i < this.ChildViews.length; i++) {
|
|
1164
|
+
this.ChildViews[i].StopAllAnimations();
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
/**
|
|
1169
|
+
* 获得正在进行动的动画的句柄
|
|
1170
|
+
*
|
|
1171
|
+
* @public
|
|
1172
|
+
* @func GetAnimation
|
|
1173
|
+
* @memberof Forge.LayoutViewBase
|
|
1174
|
+
* @instance
|
|
1175
|
+
* @return {Forge.AnimationBase}
|
|
1176
|
+
* */
|
|
1177
|
+
GetAnimation() {
|
|
1178
|
+
return this.TransformAnimationObj;
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
/**
|
|
1182
|
+
* 移除动画设置。<br>
|
|
1183
|
+
* 架构内部函数,应只能被Forge.AnimationBase调用
|
|
1184
|
+
*
|
|
1185
|
+
* @func DetachAnimation
|
|
1186
|
+
* @memberof Forge.LayoutViewBase
|
|
1187
|
+
* @instance
|
|
1188
|
+
* @param {Forge.AnimationBase} anim 要移除的动画
|
|
1189
|
+
* */
|
|
1190
|
+
DetachAnimation(anim) {
|
|
1191
|
+
if (this.TransformAnimationObj === anim) {
|
|
1192
|
+
this.TransformAnimationObj = null;
|
|
1193
|
+
|
|
1194
|
+
if (!window.jsvInAndroidWebView) {
|
|
1195
|
+
this.Element.style.animation = null;
|
|
1196
|
+
this.Element.style.transition = null;
|
|
1197
|
+
} else {
|
|
1198
|
+
this.Element.style.webkitAnimation = null;
|
|
1199
|
+
this.Element.style.webkitTransition = null;
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
ResetCssTransform(transform_string, transform_origin_string) {
|
|
1205
|
+
if (
|
|
1206
|
+
transform_string !== this._CssTransform ||
|
|
1207
|
+
transform_origin_string !== this._CssTransformOrigin
|
|
1208
|
+
) {
|
|
1209
|
+
// console.log("ResetCssTransform transform_string:", transform_string);
|
|
1210
|
+
if (!window.jsvInAndroidWebView) {
|
|
1211
|
+
this.Element.style.transform = transform_string;
|
|
1212
|
+
this.Element.style.transformOrigin = transform_origin_string;
|
|
1213
|
+
} else {
|
|
1214
|
+
this.Element.style.webkitTransform = transform_string;
|
|
1215
|
+
this.Element.style.webkitTransformOrigin = transform_origin_string;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
this._CssTransform = transform_string;
|
|
1219
|
+
this._CssTransformOrigin = transform_origin_string;
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
ResetTextureCssTransform(transform_string, transform_origin_string) {
|
|
1224
|
+
this.ResetCssTransform(transform_string, transform_origin_string);
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
/** **************************************
|
|
1228
|
+
* View getter
|
|
1229
|
+
*/
|
|
1230
|
+
SetId(id) {
|
|
1231
|
+
this.Id = id;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
ResetLayoutParams(new_params) {
|
|
1235
|
+
if (this._ProxyView != null) {
|
|
1236
|
+
// 由ProxyView代理原view的尺寸变化设置, 解决transiton动画问题
|
|
1237
|
+
this._ProxyView.ResetLayoutParams(new_params);
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
if (new_params !== null) {
|
|
1242
|
+
if (!(new_params instanceof Forge.LayoutParamsBase)) {
|
|
1243
|
+
this.LayoutParams = new Forge.LayoutParams(new_params);
|
|
1244
|
+
} else {
|
|
1245
|
+
this.LayoutParams = new_params.Clone();
|
|
1246
|
+
}
|
|
1247
|
+
this.Element.style.left = `${this.LayoutParams.MarginLeft}px`;
|
|
1248
|
+
this.Element.style.top = `${this.LayoutParams.MarginTop}px`;
|
|
1249
|
+
if (this.LayoutParams.Width) {
|
|
1250
|
+
this.Element.style.width = `${this.LayoutParams.Width}px`;
|
|
1251
|
+
}
|
|
1252
|
+
if (this.LayoutParams.Height) {
|
|
1253
|
+
this.Element.style.height = `${this.LayoutParams.Height}px`;
|
|
1254
|
+
}
|
|
1255
|
+
} else {
|
|
1256
|
+
Forge.ThrowError("ResetLayoutParams(): new params is null");
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
/**
|
|
1261
|
+
* 获得关联的Forge.Renderer
|
|
1262
|
+
*
|
|
1263
|
+
* hide public
|
|
1264
|
+
* @func GetRenderer
|
|
1265
|
+
* @memberof Forge.LayoutViewBase
|
|
1266
|
+
* @instance
|
|
1267
|
+
* @return {Forge.Renderer}
|
|
1268
|
+
* */
|
|
1269
|
+
GetRenderer() {
|
|
1270
|
+
return Forge.LayoutViewBase.sRenderer;
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
/**
|
|
1274
|
+
* 获得当前布局配置的拷贝
|
|
1275
|
+
*
|
|
1276
|
+
* @public
|
|
1277
|
+
* @func GetLayoutParams
|
|
1278
|
+
* @memberof Forge.LayoutViewBase
|
|
1279
|
+
* @instance
|
|
1280
|
+
* @return {Forge.LayoutParams}
|
|
1281
|
+
* */
|
|
1282
|
+
GetLayoutParams() {
|
|
1283
|
+
if (!this.LayoutParams) {
|
|
1284
|
+
return new Forge.LayoutParams();
|
|
1285
|
+
}
|
|
1286
|
+
return this.LayoutParams.Clone();
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
/**
|
|
1290
|
+
* 启用自适应高度
|
|
1291
|
+
*
|
|
1292
|
+
* @public
|
|
1293
|
+
* @func EnableAutoHeight
|
|
1294
|
+
* @memberof Forge.LayoutViewBase
|
|
1295
|
+
* @instance
|
|
1296
|
+
* */
|
|
1297
|
+
EnableAutoHeight() {
|
|
1298
|
+
this._AutoHeight = true;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
// 功能: 标识本LayoutView要根据自身Texture加载完成后,根据Texture的尺寸重新Resize
|
|
1302
|
+
// 当enable后,无论尺寸设成多少,同步给Native的界面尺寸都会固定为(1,1),
|
|
1303
|
+
// 以保证View会被渲染,从而防止Texture由于不在界面上不会加载的处理生效,同时小尺寸不会被注意
|
|
1304
|
+
// JsView根据这个信息判断是否在屏幕内,而决定是否进行加载(屏幕外内容不加载以节省内存)
|
|
1305
|
+
WaitTextureToResize(enable) {
|
|
1306
|
+
// js模式下为控制显示和隐藏
|
|
1307
|
+
// 这边控制显隐会导致用户端设置ninepatch为隐藏时,这边将其显示
|
|
1308
|
+
// this.Element.style.visibility = enable ? "hidden" : "visible";
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
// 根据object fit,调整texture在view中的显示位置
|
|
1312
|
+
// 当view的宽/高,单项为0时,可以进行内容的自适应扩展
|
|
1313
|
+
ApplyObjectFit(
|
|
1314
|
+
frame_width,
|
|
1315
|
+
frame_height,
|
|
1316
|
+
texture_width,
|
|
1317
|
+
texture_height,
|
|
1318
|
+
object_fit,
|
|
1319
|
+
object_fit_define
|
|
1320
|
+
) {
|
|
1321
|
+
if (this._ObjectFitTestCache === null) {
|
|
1322
|
+
// 创建检测结果的缓存,用于加快检测速度
|
|
1323
|
+
this._ObjectFitTestCache = {
|
|
1324
|
+
frameWidth: NaN,
|
|
1325
|
+
frameHeight: NaN,
|
|
1326
|
+
textureWidth: NaN,
|
|
1327
|
+
textureHeight: NaN,
|
|
1328
|
+
objectFit: null,
|
|
1329
|
+
clipLayout: null,
|
|
1330
|
+
};
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
const test_cache = this._ObjectFitTestCache;
|
|
1334
|
+
|
|
1335
|
+
if (
|
|
1336
|
+
test_cache.frameWidth === frame_width &&
|
|
1337
|
+
test_cache.objectFit === object_fit &&
|
|
1338
|
+
test_cache.frameHeight === frame_height &&
|
|
1339
|
+
test_cache.textureWidth === texture_width &&
|
|
1340
|
+
test_cache.textureHeight === texture_height
|
|
1341
|
+
) {
|
|
1342
|
+
return test_cache.clipLayout;
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
const clip_layout = {
|
|
1346
|
+
x: 0,
|
|
1347
|
+
y: 0,
|
|
1348
|
+
width: frame_width,
|
|
1349
|
+
height: frame_height,
|
|
1350
|
+
overflow: false,
|
|
1351
|
+
};
|
|
1352
|
+
|
|
1353
|
+
// Flush cache, 放在判断处理调整viewSize之前进行cache
|
|
1354
|
+
test_cache.frameWidth = frame_width;
|
|
1355
|
+
test_cache.frameHeight = frame_height;
|
|
1356
|
+
test_cache.textureWidth = texture_width;
|
|
1357
|
+
test_cache.textureHeight = texture_height;
|
|
1358
|
+
test_cache.objectFit = object_fit;
|
|
1359
|
+
test_cache.clipLayout = clip_layout;
|
|
1360
|
+
|
|
1361
|
+
let expect_size = { width: 0, height: 0 };
|
|
1362
|
+
|
|
1363
|
+
let frame_ratio = frame_width / frame_height;
|
|
1364
|
+
const texture_ratio = texture_width / texture_height;
|
|
1365
|
+
|
|
1366
|
+
if (!texture_ratio) {
|
|
1367
|
+
console.warn("Warning:Texture size is 0!")
|
|
1368
|
+
return clip_layout;
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
if (frame_width === 0 || frame_height === 0) {
|
|
1372
|
+
if (frame_width === 0 && frame_height === 0) {
|
|
1373
|
+
// frame没有size的场合
|
|
1374
|
+
return clip_layout;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
// 调整frame width 和 frame height,并计算新的frame ratio
|
|
1378
|
+
if (frame_width === 0) {
|
|
1379
|
+
frame_width = frame_height * texture_ratio;
|
|
1380
|
+
} else {
|
|
1381
|
+
// frame height === 0
|
|
1382
|
+
frame_height = frame_width / texture_ratio;
|
|
1383
|
+
}
|
|
1384
|
+
frame_ratio = frame_width / frame_height;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
let object_fit_str = "";
|
|
1388
|
+
|
|
1389
|
+
switch (object_fit) {
|
|
1390
|
+
case object_fit_define.FILL:
|
|
1391
|
+
expect_size.width = frame_width;
|
|
1392
|
+
expect_size.height = frame_height;
|
|
1393
|
+
object_fit_str = "fill";
|
|
1394
|
+
break;
|
|
1395
|
+
case object_fit_define.NONE:
|
|
1396
|
+
expect_size.width = texture_width;
|
|
1397
|
+
expect_size.height = texture_height;
|
|
1398
|
+
object_fit_str = "none";
|
|
1399
|
+
break;
|
|
1400
|
+
case object_fit_define.COVER:
|
|
1401
|
+
expect_size = this._StretchSize(
|
|
1402
|
+
frame_width,
|
|
1403
|
+
frame_height,
|
|
1404
|
+
texture_ratio,
|
|
1405
|
+
texture_ratio < frame_ratio
|
|
1406
|
+
);
|
|
1407
|
+
object_fit_str = "cover";
|
|
1408
|
+
break;
|
|
1409
|
+
case object_fit_define.SCALEDOWN: {
|
|
1410
|
+
// 使用contain和none之间尺寸小的一个。
|
|
1411
|
+
let refer_width = texture_ratio > frame_ratio; // use object-fit.contain
|
|
1412
|
+
if (frame_width > texture_width && frame_height > texture_height) {
|
|
1413
|
+
// use object-fit.none
|
|
1414
|
+
refer_width = texture_ratio < frame_ratio; // use object-fit.contain
|
|
1415
|
+
}
|
|
1416
|
+
expect_size = this._StretchSize(
|
|
1417
|
+
frame_width,
|
|
1418
|
+
frame_height,
|
|
1419
|
+
texture_ratio,
|
|
1420
|
+
refer_width
|
|
1421
|
+
);
|
|
1422
|
+
object_fit_str = "scaledown";
|
|
1423
|
+
break;
|
|
1424
|
+
}
|
|
1425
|
+
case object_fit_define.CONTAIN:
|
|
1426
|
+
expect_size = this._StretchSize(
|
|
1427
|
+
frame_width,
|
|
1428
|
+
frame_height,
|
|
1429
|
+
texture_ratio,
|
|
1430
|
+
texture_ratio > frame_ratio
|
|
1431
|
+
);
|
|
1432
|
+
// console.warn("Element.JsvFitViewLayout() expect_size=" + JSON.stringify(expect_size));
|
|
1433
|
+
object_fit_str = "contain";
|
|
1434
|
+
break;
|
|
1435
|
+
default:
|
|
1436
|
+
throw new Error("Unexpected object-fit.");
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
// format expect size
|
|
1440
|
+
expect_size.width = Math.floor(expect_size.width);
|
|
1441
|
+
expect_size.height = Math.floor(expect_size.height);
|
|
1442
|
+
|
|
1443
|
+
// 计算可视区域
|
|
1444
|
+
clip_layout.width = Math.min(expect_size.width, frame_width);
|
|
1445
|
+
clip_layout.height = Math.min(expect_size.height, frame_height);
|
|
1446
|
+
clip_layout.x = Math.floor((frame_width - clip_layout.width) / 2);
|
|
1447
|
+
clip_layout.y = Math.floor((frame_height - clip_layout.height) / 2);
|
|
1448
|
+
clip_layout.overflow =
|
|
1449
|
+
expect_size.width > frame_width || expect_size.height > frame_height;
|
|
1450
|
+
|
|
1451
|
+
// element设置object fit
|
|
1452
|
+
const target_ele = this.InnerChildElement
|
|
1453
|
+
? this.InnerChildElement
|
|
1454
|
+
: this.Element;
|
|
1455
|
+
target_ele.style.width = `${frame_width}px`;
|
|
1456
|
+
target_ele.style.height = `${frame_height}px`;
|
|
1457
|
+
target_ele.style.objectFit = object_fit_str;
|
|
1458
|
+
|
|
1459
|
+
return clip_layout;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
_StretchSize(origin_width, origin_height, ratio, refer_width) {
|
|
1463
|
+
const stretchSize = { width: 0, height: 0 };
|
|
1464
|
+
|
|
1465
|
+
if (refer_width) {
|
|
1466
|
+
stretchSize.width = origin_width;
|
|
1467
|
+
stretchSize.height = origin_width / ratio;
|
|
1468
|
+
} else {
|
|
1469
|
+
stretchSize.height = origin_height;
|
|
1470
|
+
stretchSize.width = origin_height * ratio;
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
return stretchSize;
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
/**
|
|
1477
|
+
* 注意:改坐标计算过程中,只通过LayoutParams进行计算,不计算变形矩阵
|
|
1478
|
+
*
|
|
1479
|
+
* @func GetPositionOffset
|
|
1480
|
+
* @memberof Forge.LayoutViewBase
|
|
1481
|
+
* @instance
|
|
1482
|
+
* @param {Forge.LayoutViewBase} target_parent Offset测试目标父节点的LayoutView
|
|
1483
|
+
* @return {Forge.Coordinate} 坐标值
|
|
1484
|
+
* */
|
|
1485
|
+
GetPositionOffset(target_parent) {
|
|
1486
|
+
let test_view = this;
|
|
1487
|
+
let x_offset = 0;
|
|
1488
|
+
let y_offset = 0;
|
|
1489
|
+
while (target_parent !== test_view) {
|
|
1490
|
+
x_offset += test_view.LayoutParams
|
|
1491
|
+
? test_view.LayoutParams.MarginLeft
|
|
1492
|
+
: 0;
|
|
1493
|
+
y_offset += test_view.LayoutParams ? test_view.LayoutParams.MarginTop : 0;
|
|
1494
|
+
test_view = test_view.ParentView;
|
|
1495
|
+
if (!test_view)
|
|
1496
|
+
Forge.ThrowError(
|
|
1497
|
+
"ERROR: Target parent layoutview is not found in LayoutView tree"
|
|
1498
|
+
);
|
|
1499
|
+
}
|
|
1500
|
+
return new Forge.Coordinate(x_offset, y_offset);
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
_dispatchLongPress() {
|
|
1504
|
+
this._LongPressDelayRequestTaskId = 0;
|
|
1505
|
+
this._InLongPress = true;
|
|
1506
|
+
const target_event = {
|
|
1507
|
+
type: Forge.DragInfo.EVENT_TYPE.OnLongPress,
|
|
1508
|
+
x: this._CurrentDownEvent.designX,
|
|
1509
|
+
y: this._CurrentDownEvent.designY,
|
|
1510
|
+
};
|
|
1511
|
+
this.TouchEventProcess(target_event);
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
_onMouseDown(designX, designY, timeStamp) {
|
|
1515
|
+
// reset velocity
|
|
1516
|
+
this._Velocity.x.reset();
|
|
1517
|
+
this._Velocity.y.reset();
|
|
1518
|
+
this._Velocity.x.updatePosition(designX);
|
|
1519
|
+
this._Velocity.y.updatePosition(designY);
|
|
1520
|
+
this._LastFocusX = designX;
|
|
1521
|
+
this._DownFocusX = this._LastFocusX;
|
|
1522
|
+
this._LastFocusY = designY;
|
|
1523
|
+
this._DownFocusY = this._LastFocusY;
|
|
1524
|
+
this._CurrentDownEvent = { designX, designY, timeStamp };
|
|
1525
|
+
this._AlwaysInTapRegion = true;
|
|
1526
|
+
|
|
1527
|
+
// 重置long press状态
|
|
1528
|
+
this._InLongPress = false;
|
|
1529
|
+
if (this._LongPressDelayRequestTaskId !== 0) {
|
|
1530
|
+
clearTimeout(this._LongPressDelayRequestTaskId);
|
|
1531
|
+
this._LongPressDelayRequestTaskId = 0;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
this._LongPressDelayRequestTaskId = setTimeout(
|
|
1535
|
+
this._dispatchLongPress,
|
|
1536
|
+
600
|
|
1537
|
+
);
|
|
1538
|
+
const target_event = {
|
|
1539
|
+
type: Forge.DragInfo.EVENT_TYPE.OnDown,
|
|
1540
|
+
x: designX,
|
|
1541
|
+
y: designY,
|
|
1542
|
+
deltaX: 0,
|
|
1543
|
+
deltaY: 0,
|
|
1544
|
+
};
|
|
1545
|
+
return target_event;
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
_onMouseMove(designX, designY, timeStamp) {
|
|
1549
|
+
if (!this._CurrentDownEvent) {
|
|
1550
|
+
return null;
|
|
1551
|
+
}
|
|
1552
|
+
this._Velocity.x.updatePosition(designX);
|
|
1553
|
+
this._Velocity.y.updatePosition(designY);
|
|
1554
|
+
const deltaX = parseInt(designX - this._LastFocusX, 10);
|
|
1555
|
+
const deltaY = parseInt(designY - this._LastFocusY, 10);
|
|
1556
|
+
const distanceX = parseInt(designX - this._DownFocusX, 10);
|
|
1557
|
+
const distanceY = parseInt(designY - this._DownFocusY, 10);
|
|
1558
|
+
let target_event = null;
|
|
1559
|
+
if (this._AlwaysInTapRegion) {
|
|
1560
|
+
const distance = distanceX * distanceX + distanceY * distanceY;
|
|
1561
|
+
const slopSquare = this._TouchSlopSquare;
|
|
1562
|
+
if (distance > slopSquare) {
|
|
1563
|
+
target_event = {
|
|
1564
|
+
type: Forge.DragInfo.EVENT_TYPE.OnDragStart,
|
|
1565
|
+
x: designX,
|
|
1566
|
+
y: designY,
|
|
1567
|
+
};
|
|
1568
|
+
this._LastFocusX = designX;
|
|
1569
|
+
this._LastFocusY = designY;
|
|
1570
|
+
this._LastTimeStamp = timeStamp;
|
|
1571
|
+
this._AlwaysInTapRegion = false; // 状态从Tap恢复到DragStart
|
|
1572
|
+
this._InLongPress = false; // 状态从LongPress恢复到DragStart
|
|
1573
|
+
this._InDragging = true; // 进入DragMove状态
|
|
1574
|
+
if (this._LongPressDelayRequestTaskId !== 0) {
|
|
1575
|
+
clearTimeout(this._LongPressDelayRequestTaskId);
|
|
1576
|
+
this._LongPressDelayRequestTaskId = 0;
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
} else if (
|
|
1580
|
+
this._InDragging &&
|
|
1581
|
+
(Math.abs(deltaX) >= 1 || Math.abs(deltaY) >= 1)
|
|
1582
|
+
) {
|
|
1583
|
+
target_event = {
|
|
1584
|
+
type: Forge.DragInfo.EVENT_TYPE.OnMoved,
|
|
1585
|
+
x: designX,
|
|
1586
|
+
y: designY,
|
|
1587
|
+
deltaX: distanceX, // 匹配jsview touch 返回值
|
|
1588
|
+
deltaY: distanceY,
|
|
1589
|
+
_deltaX: deltaX, // 内部使用
|
|
1590
|
+
_deltaY: deltaY,
|
|
1591
|
+
|
|
1592
|
+
timeStamp: parseInt((this._LastTimeStamp - timeStamp) / 1000, 10),
|
|
1593
|
+
};
|
|
1594
|
+
this._LastFocusX = designX;
|
|
1595
|
+
this._LastFocusY = designY;
|
|
1596
|
+
this._LastTimeStamp = timeStamp;
|
|
1597
|
+
}
|
|
1598
|
+
return target_event;
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
_onMouseUp(designX, designY, timeStamp) {
|
|
1602
|
+
let target_event = null;
|
|
1603
|
+
//console.log("_onMouseUp, ", this._CurrentDownEvent);
|
|
1604
|
+
if (this._CurrentDownEvent) {
|
|
1605
|
+
const designMap = window.Forge.DesignMap();
|
|
1606
|
+
const screenBufferWidth = Math.floor(
|
|
1607
|
+
designMap.displayScale * designMap.width
|
|
1608
|
+
);
|
|
1609
|
+
const screenBufferRatio = window.innerWidth / screenBufferWidth;
|
|
1610
|
+
const designVelocityX =
|
|
1611
|
+
this._Velocity.x.getVelocity() / screenBufferRatio;
|
|
1612
|
+
const designVelocityY =
|
|
1613
|
+
this._Velocity.y.getVelocity() / screenBufferRatio;
|
|
1614
|
+
let distance_x = designX - this._CurrentDownEvent.designX;
|
|
1615
|
+
let distance_y = designY - this._CurrentDownEvent.designY;
|
|
1616
|
+
const deltaX = designX - this._LastFocusX;
|
|
1617
|
+
const deltaY = designY - this._LastFocusY;
|
|
1618
|
+
if (this._InLongPress) {
|
|
1619
|
+
// 长按状态下不处理任何事件
|
|
1620
|
+
} else if (this._AlwaysInTapRegion) {
|
|
1621
|
+
target_event = {
|
|
1622
|
+
type: Forge.DragInfo.EVENT_TYPE.OnTap,
|
|
1623
|
+
x: designX,
|
|
1624
|
+
y: designY,
|
|
1625
|
+
velocityX: 0,
|
|
1626
|
+
velocityY: 0,
|
|
1627
|
+
deltaX: distance_x,
|
|
1628
|
+
deltaY: distance_y,
|
|
1629
|
+
_deltaX: deltaX,
|
|
1630
|
+
_deltaY: deltaY,
|
|
1631
|
+
};
|
|
1632
|
+
} else {
|
|
1633
|
+
// A fling must travel the minimum tap distance
|
|
1634
|
+
// 一个fling最小的速度,单位:px/s 70
|
|
1635
|
+
if (Math.abs(designVelocityY) > 70 || Math.abs(designVelocityX) > 70) {
|
|
1636
|
+
distance_x = this._GetSplineFlingDistance(designVelocityX);
|
|
1637
|
+
distance_y = this._GetSplineFlingDistance(designVelocityY);
|
|
1638
|
+
target_event = {
|
|
1639
|
+
type: Forge.DragInfo.EVENT_TYPE.OnFling,
|
|
1640
|
+
x: designX,
|
|
1641
|
+
y: designY,
|
|
1642
|
+
velocityX: designVelocityX,
|
|
1643
|
+
velocityY: designVelocityY,
|
|
1644
|
+
deltaX: designVelocityX < 0 ? -distance_x : distance_x,
|
|
1645
|
+
deltaY: designVelocityY < 0 ? -distance_y : distance_y,
|
|
1646
|
+
_deltaX: deltaX,
|
|
1647
|
+
_deltaY: deltaY,
|
|
1648
|
+
};
|
|
1649
|
+
} else {
|
|
1650
|
+
target_event = {
|
|
1651
|
+
type: Forge.DragInfo.EVENT_TYPE.OnDragEnd,
|
|
1652
|
+
x: designX,
|
|
1653
|
+
y: designY,
|
|
1654
|
+
deltaX: distance_x,
|
|
1655
|
+
deltaY: distance_y,
|
|
1656
|
+
_deltaX: deltaX,
|
|
1657
|
+
_deltaY: deltaY,
|
|
1658
|
+
};
|
|
1659
|
+
}
|
|
1660
|
+
this.TouchEventProcess(target_event);
|
|
1661
|
+
// Release
|
|
1662
|
+
target_event = {
|
|
1663
|
+
type: Forge.DragInfo.EVENT_TYPE.OnRelease,
|
|
1664
|
+
x: designX,
|
|
1665
|
+
y: designY,
|
|
1666
|
+
deltaX: distance_x,
|
|
1667
|
+
deltaY: distance_y,
|
|
1668
|
+
_deltaX: deltaX,
|
|
1669
|
+
_deltaY: deltaY,
|
|
1670
|
+
};
|
|
1671
|
+
this._CurrentDownEvent = null;
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
// 重置long press状态
|
|
1675
|
+
this._InLongPress = false;
|
|
1676
|
+
if (this._LongPressDelayRequestTaskId !== 0) {
|
|
1677
|
+
clearTimeout(this._LongPressDelayRequestTaskId);
|
|
1678
|
+
this._LongPressDelayRequestTaskId = 0;
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
return target_event;
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
_onTouchEvent(event) {
|
|
1685
|
+
const designMap = window.Forge.DesignMap();
|
|
1686
|
+
const screenBufferWidth = Math.floor(
|
|
1687
|
+
designMap.displayScale * designMap.width
|
|
1688
|
+
);
|
|
1689
|
+
const screenBufferRatio = window.innerWidth / screenBufferWidth;
|
|
1690
|
+
const designX = event.clientX / screenBufferRatio;
|
|
1691
|
+
const designY = event.clientY / screenBufferRatio;
|
|
1692
|
+
|
|
1693
|
+
// 转换event
|
|
1694
|
+
let target_event = null;
|
|
1695
|
+
switch (event.type) {
|
|
1696
|
+
case "touchstart":
|
|
1697
|
+
case "mousedown": {
|
|
1698
|
+
target_event = this._onMouseDown(designX, designY, event.timeStamp);
|
|
1699
|
+
break;
|
|
1700
|
+
}
|
|
1701
|
+
case "touchmove":
|
|
1702
|
+
case "mousemove": {
|
|
1703
|
+
target_event = this._onMouseMove(designX, designY, event.timeStamp);
|
|
1704
|
+
break;
|
|
1705
|
+
}
|
|
1706
|
+
case "touchend":
|
|
1707
|
+
case "touchcancel":
|
|
1708
|
+
case "mouseup": {
|
|
1709
|
+
target_event = this._onMouseUp(designX, designY, event.timeStamp);
|
|
1710
|
+
break;
|
|
1711
|
+
}
|
|
1712
|
+
default:
|
|
1713
|
+
break;
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
if (target_event) {
|
|
1717
|
+
return this.TouchEventProcess(target_event);
|
|
1718
|
+
}
|
|
1719
|
+
return false;
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
_AddEventListener() {
|
|
1723
|
+
this.Element.style.pointerEvents = "auto";
|
|
1724
|
+
this._ValidTouch = false;
|
|
1725
|
+
const isTouch = "ontouchstart" in window;
|
|
1726
|
+
// console.log(`isTouch:${isTouch}`);
|
|
1727
|
+
if (isTouch) {
|
|
1728
|
+
this.Element.addEventListener(
|
|
1729
|
+
"touchstart",
|
|
1730
|
+
(event) => {
|
|
1731
|
+
console.log("touchstart", event);
|
|
1732
|
+
this._ValidTouch = true;
|
|
1733
|
+
if (event.touches && event.touches.length > 0) {
|
|
1734
|
+
console.log(
|
|
1735
|
+
`touchstart event.touches[0].clientX:${event.touches[0].clientX}, event.touches[0].clientY:${event.touches[0].clientY}`
|
|
1736
|
+
);
|
|
1737
|
+
const event_used = this._onTouchEvent({
|
|
1738
|
+
type: event.type,
|
|
1739
|
+
clientX: event.touches[0].clientX,
|
|
1740
|
+
clientY: event.touches[0].clientY,
|
|
1741
|
+
timeStamp: event.timeStamp,
|
|
1742
|
+
});
|
|
1743
|
+
if (event_used) {
|
|
1744
|
+
event.stopPropagation();
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
},
|
|
1748
|
+
true
|
|
1749
|
+
);
|
|
1750
|
+
this.Element.addEventListener(
|
|
1751
|
+
"touchmove",
|
|
1752
|
+
(event) => {
|
|
1753
|
+
if (this._ValidTouch) {
|
|
1754
|
+
console.log("touchmove", event);
|
|
1755
|
+
if (event.touches && event.touches.length > 0) {
|
|
1756
|
+
console.log(
|
|
1757
|
+
`touchmove event.touches[0].clientX:${event.touches[0].clientX}, event.touches[0].clientY:${event.touches[0].clientY}`
|
|
1758
|
+
);
|
|
1759
|
+
const event_used = this._onTouchEvent({
|
|
1760
|
+
type: event.type,
|
|
1761
|
+
clientX: event.touches[0].clientX,
|
|
1762
|
+
clientY: event.touches[0].clientY,
|
|
1763
|
+
timeStamp: event.timeStamp,
|
|
1764
|
+
});
|
|
1765
|
+
if (event_used) {
|
|
1766
|
+
event.stopPropagation();
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
},
|
|
1771
|
+
true
|
|
1772
|
+
);
|
|
1773
|
+
this.Element.addEventListener(
|
|
1774
|
+
"touchend",
|
|
1775
|
+
(event) => {
|
|
1776
|
+
console.log(
|
|
1777
|
+
`touchend event.touches.length:${event.touches.length}, event.clientX:${event.clientX}, event.pageX:${event.pageX}`
|
|
1778
|
+
);
|
|
1779
|
+
this._ValidTouch = false;
|
|
1780
|
+
if (event.changedTouches && event.changedTouches.length > 0) {
|
|
1781
|
+
console.log(
|
|
1782
|
+
`touchend event.changedTouches[0].clientX:${event.changedTouches[0].clientX}, event.changedTouches[0].pageX:${event.changedTouches[0].pageX}`
|
|
1783
|
+
);
|
|
1784
|
+
const event_used = this._onTouchEvent({
|
|
1785
|
+
type: event.type,
|
|
1786
|
+
clientX: event.changedTouches[0].clientX,
|
|
1787
|
+
clientY: event.changedTouches[0].clientY,
|
|
1788
|
+
timeStamp: event.timeStamp,
|
|
1789
|
+
});
|
|
1790
|
+
if (event_used) {
|
|
1791
|
+
event.stopPropagation();
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
},
|
|
1795
|
+
true
|
|
1796
|
+
);
|
|
1797
|
+
this.Element.addEventListener(
|
|
1798
|
+
"touchcancel",
|
|
1799
|
+
(event) => {
|
|
1800
|
+
this._ValidTouch = false;
|
|
1801
|
+
console.log("touchcancel", event);
|
|
1802
|
+
if (event.changedTouches && event.changedTouches.length > 0) {
|
|
1803
|
+
console.log(
|
|
1804
|
+
`touchcancel event.clientX:${event.clientX}, event.clientY:${event.clientY}`
|
|
1805
|
+
);
|
|
1806
|
+
const event_used = this._onTouchEvent({
|
|
1807
|
+
type: event.type,
|
|
1808
|
+
clientX: event.touches[0].clientX,
|
|
1809
|
+
clientY: event.touches[0].clientY,
|
|
1810
|
+
timeStamp: event.timeStamp,
|
|
1811
|
+
});
|
|
1812
|
+
if (event_used) {
|
|
1813
|
+
event.stopPropagation();
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
},
|
|
1817
|
+
true
|
|
1818
|
+
);
|
|
1819
|
+
} else {
|
|
1820
|
+
this.Element.addEventListener(
|
|
1821
|
+
"mousedown",
|
|
1822
|
+
(event) => {
|
|
1823
|
+
console.log("mousedown", event);
|
|
1824
|
+
this._ValidTouch = true;
|
|
1825
|
+
const event_used = this._onTouchEvent(event);
|
|
1826
|
+
if (event_used) {
|
|
1827
|
+
event.stopPropagation();
|
|
1828
|
+
}
|
|
1829
|
+
},
|
|
1830
|
+
true
|
|
1831
|
+
);
|
|
1832
|
+
|
|
1833
|
+
this.Element.addEventListener(
|
|
1834
|
+
"mousemove",
|
|
1835
|
+
(event) => {
|
|
1836
|
+
if (this._ValidTouch) {
|
|
1837
|
+
const event_used = this._onTouchEvent(event);
|
|
1838
|
+
if (event_used) {
|
|
1839
|
+
event.stopPropagation();
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
},
|
|
1843
|
+
true
|
|
1844
|
+
);
|
|
1845
|
+
|
|
1846
|
+
this.Element.addEventListener(
|
|
1847
|
+
"mouseup",
|
|
1848
|
+
(event) => {
|
|
1849
|
+
console.log("mouseup", event);
|
|
1850
|
+
this._ValidTouch = false;
|
|
1851
|
+
const event_used = this._onTouchEvent(event);
|
|
1852
|
+
if (event_used) {
|
|
1853
|
+
event.stopPropagation();
|
|
1854
|
+
}
|
|
1855
|
+
},
|
|
1856
|
+
true
|
|
1857
|
+
);
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
/*
|
|
1862
|
+
_GetSplineFlingDuration(velocity) {
|
|
1863
|
+
let l = this._GetSplineDeceleration(velocity);
|
|
1864
|
+
let decelMinusOne = Forge.DragInfo.DECELERATION_RATE - 1.0;
|
|
1865
|
+
return parseInt(1000.0 * Math.exp(l / decelMinusOne));
|
|
1866
|
+
}
|
|
1867
|
+
*/
|
|
1868
|
+
// 减速带
|
|
1869
|
+
_GetSplineDeceleration(velocity) {
|
|
1870
|
+
return Math.log(
|
|
1871
|
+
(Forge.DragInfo.INFLEXION * Math.abs(velocity)) /
|
|
1872
|
+
(Forge.DragInfo.SCROLL_FRICTION * Forge.DragInfo.PHYSICAL_COEF)
|
|
1873
|
+
);
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
_GetSplineFlingDistance(velocity) {
|
|
1877
|
+
const l = this._GetSplineDeceleration(velocity);
|
|
1878
|
+
const decelMinusOne = Forge.DragInfo.DECELERATION_RATE - 1.0;
|
|
1879
|
+
return (
|
|
1880
|
+
Forge.DragInfo.SCROLL_FRICTION *
|
|
1881
|
+
Forge.DragInfo.PHYSICAL_COEF *
|
|
1882
|
+
Math.exp((Forge.DragInfo.DECELERATION_RATE / decelMinusOne) * l)
|
|
1883
|
+
);
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
_DoDragMove(event, need_anim) {
|
|
1887
|
+
let deltaX = event._deltaX;
|
|
1888
|
+
let deltaY = event._deltaY;
|
|
1889
|
+
this._DragMovedDistanceX += deltaX;
|
|
1890
|
+
this._DragMovedDistanceY += deltaY;
|
|
1891
|
+
if (!need_anim) {
|
|
1892
|
+
// onFling时,dragmove不更新view坐标,故用deltaX,不使用内部的_deltaX。
|
|
1893
|
+
deltaX = event.deltaX;
|
|
1894
|
+
deltaY = event.deltaY;
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
const duration = event.timeStamp / 1000;
|
|
1898
|
+
let transition = `left ${duration}s, top ${duration}s`;
|
|
1899
|
+
if (
|
|
1900
|
+
this._DragInfo.Settings.DragDirection ===
|
|
1901
|
+
Forge.DragSetting.DIRECTION_VERTICAL
|
|
1902
|
+
) {
|
|
1903
|
+
deltaX = 0;
|
|
1904
|
+
transition = `top ${duration}s`;
|
|
1905
|
+
} else if (
|
|
1906
|
+
this._DragInfo.Settings.DragDirection ===
|
|
1907
|
+
Forge.DragSetting.DIRECTION_HORIZONTAL
|
|
1908
|
+
) {
|
|
1909
|
+
deltaY = 0;
|
|
1910
|
+
transition = `left ${duration}s`;
|
|
1911
|
+
} else if (
|
|
1912
|
+
this._DragInfo.Settings.DragDirection ===
|
|
1913
|
+
Forge.DragSetting.DIRECTION_DISABLE
|
|
1914
|
+
) {
|
|
1915
|
+
deltaX = 0;
|
|
1916
|
+
deltaY = 0;
|
|
1917
|
+
}
|
|
1918
|
+
let lp = this.GetLayoutParams();
|
|
1919
|
+
// const viewX = lp.MarginLeft;
|
|
1920
|
+
// const viewY = lp.MarginTop;
|
|
1921
|
+
// 检测边界
|
|
1922
|
+
lp = this._GetMovedLayoutParams(deltaX, deltaY);
|
|
1923
|
+
if (need_anim) {
|
|
1924
|
+
this.Element.style.transition = transition;
|
|
1925
|
+
this.ResetLayoutParams(lp);
|
|
1926
|
+
}
|
|
1927
|
+
if (
|
|
1928
|
+
Math.abs(this._DragMovedDistanceX) >=
|
|
1929
|
+
this._DragInfo.Settings.TriggerMovedDistance ||
|
|
1930
|
+
Math.abs(this._DragMovedDistanceY) >=
|
|
1931
|
+
this._DragInfo.Settings.TriggerMovedDistance
|
|
1932
|
+
) {
|
|
1933
|
+
if (this._DragInfo.Listener && this._DragInfo.Listener.OnMoved) {
|
|
1934
|
+
// 补充event
|
|
1935
|
+
event.viewX = lp.MarginLeft;
|
|
1936
|
+
event.viewY = lp.MarginTop;
|
|
1937
|
+
return this._DragInfo.Listener.OnMoved(event);
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
return false;
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
_GetMovedLayoutParams(deltaX, deltaY) {
|
|
1944
|
+
const lp = this.GetLayoutParams();
|
|
1945
|
+
let x = lp.MarginLeft + deltaX;
|
|
1946
|
+
let y = lp.MarginTop + deltaY;
|
|
1947
|
+
|
|
1948
|
+
if (x > this._DragInfo.Settings.SlidePile.x) {
|
|
1949
|
+
x = this._DragInfo.Settings.SlidePile.x;
|
|
1950
|
+
} else if (
|
|
1951
|
+
x + lp.Width <
|
|
1952
|
+
this._DragInfo.Settings.SlidePile.x +
|
|
1953
|
+
this._DragInfo.Settings.SlidePile.width
|
|
1954
|
+
) {
|
|
1955
|
+
x =
|
|
1956
|
+
this._DragInfo.Settings.SlidePile.x +
|
|
1957
|
+
this._DragInfo.Settings.SlidePile.width -
|
|
1958
|
+
lp.Width;
|
|
1959
|
+
}
|
|
1960
|
+
if (y > this._DragInfo.Settings.SlidePile.y) {
|
|
1961
|
+
y = this._DragInfo.Settings.SlidePile.y;
|
|
1962
|
+
} else if (
|
|
1963
|
+
y + lp.Height <
|
|
1964
|
+
this._DragInfo.Settings.SlidePile.y +
|
|
1965
|
+
this._DragInfo.Settings.SlidePile.height
|
|
1966
|
+
) {
|
|
1967
|
+
y =
|
|
1968
|
+
this._DragInfo.Settings.SlidePile.y +
|
|
1969
|
+
this._DragInfo.Settings.SlidePile.height -
|
|
1970
|
+
lp.Height;
|
|
1971
|
+
}
|
|
1972
|
+
lp.SetPosition(x, y);
|
|
1973
|
+
|
|
1974
|
+
return lp;
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
_SlideIfEnableTabMod(event, direction) {
|
|
1978
|
+
if (!this._DragInfo.Settings.EnableTabMode) {
|
|
1979
|
+
return false;
|
|
1980
|
+
}
|
|
1981
|
+
const deltaX = event._deltaX;
|
|
1982
|
+
const deltaY = event._deltaY;
|
|
1983
|
+
let distance_x = event.deltaX;
|
|
1984
|
+
let distance_y = event.deltaY;
|
|
1985
|
+
let page_edge =
|
|
1986
|
+
this._DragInfo.Settings.PageWidth * this._DragInfo.Settings.PageEdge;
|
|
1987
|
+
const lp = this.GetLayoutParams();
|
|
1988
|
+
const viewX = lp.MarginLeft + deltaX;
|
|
1989
|
+
const viewY = lp.MarginTop + deltaY;
|
|
1990
|
+
if (event.type === Forge.DragInfo.EVENT_TYPE.OnFling) {
|
|
1991
|
+
page_edge = 0; // fling时,不进行edge判断
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
// 计算
|
|
1995
|
+
switch (this._DragInfo.Settings.DragDirection) {
|
|
1996
|
+
case Forge.DragSetting.DIRECTION_VERTICAL: {
|
|
1997
|
+
// 当拖拽的距离大于等于limitrange时,进行同向动画,否则动画相反
|
|
1998
|
+
distance_x = 0;
|
|
1999
|
+
// 重置duration 与 距离
|
|
2000
|
+
if (distance_y >= 0) {
|
|
2001
|
+
const left_width =
|
|
2002
|
+
this._DragInfo.Settings.PageWidth -
|
|
2003
|
+
(Math.abs(viewY) % this._DragInfo.Settings.PageWidth);
|
|
2004
|
+
if (left_width >= page_edge) {
|
|
2005
|
+
distance_y = this._DragInfo.Settings.PageWidth - left_width;
|
|
2006
|
+
} else {
|
|
2007
|
+
distance_y = -left_width;
|
|
2008
|
+
}
|
|
2009
|
+
} else {
|
|
2010
|
+
const left_width =
|
|
2011
|
+
Math.abs(viewY) % this._DragInfo.Settings.PageWidth;
|
|
2012
|
+
if (left_width >= page_edge) {
|
|
2013
|
+
distance_y = -(this._DragInfo.Settings.PageWidth - left_width);
|
|
2014
|
+
} else {
|
|
2015
|
+
distance_y = left_width;
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
break;
|
|
2019
|
+
}
|
|
2020
|
+
case Forge.DragSetting.DIRECTION_HORIZONTAL: {
|
|
2021
|
+
distance_y = 0;
|
|
2022
|
+
if (distance_x >= 0) {
|
|
2023
|
+
const left_width =
|
|
2024
|
+
this._DragInfo.Settings.PageWidth -
|
|
2025
|
+
(Math.abs(viewX) % this._DragInfo.Settings.PageWidth);
|
|
2026
|
+
if (left_width >= page_edge) {
|
|
2027
|
+
distance_x = this._DragInfo.Settings.PageWidth - left_width;
|
|
2028
|
+
} else {
|
|
2029
|
+
distance_x = -left_width;
|
|
2030
|
+
}
|
|
2031
|
+
console.log(
|
|
2032
|
+
`right, left_width:${left_width}, distance_x:${distance_x}`
|
|
2033
|
+
);
|
|
2034
|
+
} else {
|
|
2035
|
+
const left_width =
|
|
2036
|
+
Math.abs(viewX) % this._DragInfo.Settings.PageWidth;
|
|
2037
|
+
if (left_width >= page_edge) {
|
|
2038
|
+
distance_x = -(this._DragInfo.Settings.PageWidth - left_width);
|
|
2039
|
+
} else {
|
|
2040
|
+
distance_x = left_width;
|
|
2041
|
+
}
|
|
2042
|
+
console.log(
|
|
2043
|
+
`left, left_width:${left_width}, distance_x:${distance_x}`
|
|
2044
|
+
);
|
|
2045
|
+
}
|
|
2046
|
+
break;
|
|
2047
|
+
}
|
|
2048
|
+
case Forge.DragSetting.DIRECTION_AUTO: {
|
|
2049
|
+
console.log(
|
|
2050
|
+
"slideIfEnableTabMode DragDirection error DRAG_DIRECTION_AUTO"
|
|
2051
|
+
);
|
|
2052
|
+
break;
|
|
2053
|
+
}
|
|
2054
|
+
default:
|
|
2055
|
+
break;
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
if (distance_x === 0 && distance_y === 0) {
|
|
2059
|
+
console.log("slideIfEnableTabMode distance_x === 0 && distance_y === 0");
|
|
2060
|
+
return false;
|
|
2061
|
+
}
|
|
2062
|
+
const speed =
|
|
2063
|
+
Math.sqrt(distance_x * distance_x + distance_y * distance_y) / 0.3; // 与jsview 效果匹配,300ms完成动画
|
|
2064
|
+
event.deltaX = distance_x;
|
|
2065
|
+
event.deltaY = distance_y;
|
|
2066
|
+
this._DonFlingAnim(event, speed);
|
|
2067
|
+
return true;
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
_DoDragEnd(event) {
|
|
2071
|
+
let deltaX = event._deltaX;
|
|
2072
|
+
let deltaY = event._deltaY;
|
|
2073
|
+
if (
|
|
2074
|
+
this._DragInfo.Settings.DragDirection ===
|
|
2075
|
+
Forge.DragSetting.DIRECTION_VERTICAL
|
|
2076
|
+
) {
|
|
2077
|
+
deltaX = 0;
|
|
2078
|
+
} else if (
|
|
2079
|
+
this._DragInfo.Settings.DragDirection ===
|
|
2080
|
+
Forge.DragSetting.DIRECTION_HORIZONTAL
|
|
2081
|
+
) {
|
|
2082
|
+
deltaY = 0;
|
|
2083
|
+
} else if (
|
|
2084
|
+
this._DragInfo.Settings.DragDirection ===
|
|
2085
|
+
Forge.DragSetting.DIRECTION_DISABLE
|
|
2086
|
+
) {
|
|
2087
|
+
deltaX = 0;
|
|
2088
|
+
deltaY = 0;
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
console.log("_DoDragEnd event:", event, this.Element.style);
|
|
2092
|
+
let lp = this.GetLayoutParams();
|
|
2093
|
+
// 检测边界
|
|
2094
|
+
lp = this._GetMovedLayoutParams(deltaX, deltaY);
|
|
2095
|
+
this.ResetLayoutParams(lp);
|
|
2096
|
+
|
|
2097
|
+
// 补充event
|
|
2098
|
+
event.viewX = lp.MarginLeft;
|
|
2099
|
+
event.viewY = lp.MarginTop;
|
|
2100
|
+
|
|
2101
|
+
return this._DragInfo.Listener.OnDragEnd(event);
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
_DragImactSensorRecycle() {
|
|
2105
|
+
console.log(
|
|
2106
|
+
"_DragImactSensorRecycle this._DragImactSensor:",
|
|
2107
|
+
this._DragImactSensor
|
|
2108
|
+
);
|
|
2109
|
+
if (this._DragImactSensor) {
|
|
2110
|
+
this._DragImactSensor.Recycle();
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
_DonFlingAnim(event, speed) {
|
|
2115
|
+
const distance_x = event.deltaX;
|
|
2116
|
+
const distance_y = event.deltaY;
|
|
2117
|
+
const lp = this.GetLayoutParams();
|
|
2118
|
+
const view_origin_x = lp.MarginLeft;
|
|
2119
|
+
const view_origin_y = lp.MarginTop;
|
|
2120
|
+
const target_x = lp.MarginLeft + distance_x;
|
|
2121
|
+
const target_y = lp.MarginTop + distance_y;
|
|
2122
|
+
const adjust_lp = this._GetMovedLayoutParams(distance_x, distance_y);
|
|
2123
|
+
if (
|
|
2124
|
+
adjust_lp.MarginLeft === lp.MarginLeft &&
|
|
2125
|
+
adjust_lp.MarginTop === lp.MarginTop
|
|
2126
|
+
) {
|
|
2127
|
+
console.log(
|
|
2128
|
+
"_DonFlingAnim adjust_lp.MarginLeft === lp.MarginLeft && adjust_lp.MarginTop === lp.MarginTop"
|
|
2129
|
+
);
|
|
2130
|
+
return;
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
this.DragControl = new Forge.DragTranslateControl();
|
|
2134
|
+
this.DragControl._SetView(this);
|
|
2135
|
+
this.DragControl.speed(speed);
|
|
2136
|
+
console.log(`OnFling speed:${speed}`);
|
|
2137
|
+
const setting = this._DragInfo.Settings;
|
|
2138
|
+
this._DragImactSensorRecycle();
|
|
2139
|
+
|
|
2140
|
+
this.Element.style.transform = null;
|
|
2141
|
+
this.DragControl.target(lp.MarginLeft, lp.MarginTop).jumpSilent();
|
|
2142
|
+
// TODO 需确认,恢复view的坐标,进行动画,否则碰撞检测时,会使用坐标并将其于transform translate合计,导致碰撞错误
|
|
2143
|
+
lp.SetPosition(0, 0);
|
|
2144
|
+
this.ResetLayoutParams(lp);
|
|
2145
|
+
let timeStamp = 0;
|
|
2146
|
+
|
|
2147
|
+
this.DragControl.target(target_x, target_y).start(
|
|
2148
|
+
(view_x, view_y) => {
|
|
2149
|
+
this.DragControl = null;
|
|
2150
|
+
lp.SetPosition(view_x, view_y);
|
|
2151
|
+
this.ResetLayoutParams(lp);
|
|
2152
|
+
this.Element.style.transform = null;
|
|
2153
|
+
this._DragImactSensorRecycle();
|
|
2154
|
+
|
|
2155
|
+
// 补充event
|
|
2156
|
+
event.viewX = view_x;
|
|
2157
|
+
event.viewY = view_y;
|
|
2158
|
+
this._DragInfo.Listener.OnFling(event);
|
|
2159
|
+
console.log(
|
|
2160
|
+
`_DonFlingAnim end view_x:${view_x}, view_y:${view_y}, distance_x:${distance_x}, distance_y:${distance_y}`
|
|
2161
|
+
);
|
|
2162
|
+
},
|
|
2163
|
+
(progress) => {
|
|
2164
|
+
const deltaX = distance_x * progress;
|
|
2165
|
+
const deltaY = distance_y * progress;
|
|
2166
|
+
console.log(
|
|
2167
|
+
`_DonFlingAnim progress:${progress}, deltaX:${deltaX}, deltaY:${deltaY}`
|
|
2168
|
+
);
|
|
2169
|
+
if (
|
|
2170
|
+
Math.abs(deltaX) > this._DragInfo.Settings.TriggerMovedDistance ||
|
|
2171
|
+
Math.abs(deltaY) > this._DragInfo.Settings.TriggerMovedDistance
|
|
2172
|
+
) {
|
|
2173
|
+
const target_event = {
|
|
2174
|
+
deltaX: view_origin_x + deltaX,
|
|
2175
|
+
deltaY: view_origin_y + deltaY,
|
|
2176
|
+
_deltaX: deltaX,
|
|
2177
|
+
_deltaY: deltaY,
|
|
2178
|
+
timeStamp: parseInt((Date.now() - timeStamp) / 1000, 10),
|
|
2179
|
+
};
|
|
2180
|
+
this._DoDragMove(target_event, false);
|
|
2181
|
+
timeStamp = Date.now();
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
);
|
|
2185
|
+
const parent_view_position = this.GetPositionOffset(this.ParentView);
|
|
2186
|
+
// 设置碰撞sensor
|
|
2187
|
+
this._DragImactSensor = new Forge.DragImpactSensor(
|
|
2188
|
+
[
|
|
2189
|
+
{
|
|
2190
|
+
x: setting.SlidePile.x + parent_view_position.x,
|
|
2191
|
+
y: setting.SlidePile.y + parent_view_position.y,
|
|
2192
|
+
},
|
|
2193
|
+
{
|
|
2194
|
+
x:
|
|
2195
|
+
setting.SlidePile.x +
|
|
2196
|
+
parent_view_position.x +
|
|
2197
|
+
setting.SlidePile.width,
|
|
2198
|
+
y: setting.SlidePile.y + parent_view_position.y,
|
|
2199
|
+
},
|
|
2200
|
+
{
|
|
2201
|
+
x: setting.SlidePile.x + parent_view_position.x,
|
|
2202
|
+
y:
|
|
2203
|
+
setting.SlidePile.y +
|
|
2204
|
+
parent_view_position.y +
|
|
2205
|
+
setting.SlidePile.height,
|
|
2206
|
+
},
|
|
2207
|
+
{
|
|
2208
|
+
x:
|
|
2209
|
+
setting.SlidePile.x +
|
|
2210
|
+
parent_view_position.x +
|
|
2211
|
+
setting.SlidePile.width,
|
|
2212
|
+
y:
|
|
2213
|
+
setting.SlidePile.y +
|
|
2214
|
+
parent_view_position.y +
|
|
2215
|
+
setting.SlidePile.height,
|
|
2216
|
+
},
|
|
2217
|
+
],
|
|
2218
|
+
this.Element,
|
|
2219
|
+
new Forge.sImpactSensorManager.Callback((element_position) => {
|
|
2220
|
+
this._DoDragPause(event);
|
|
2221
|
+
this._DragImactSensorRecycle();
|
|
2222
|
+
}, null)
|
|
2223
|
+
);
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
_DoFling(event) {
|
|
2227
|
+
let distance_x = event.deltaX;
|
|
2228
|
+
let distance_y = event.deltaY;
|
|
2229
|
+
let need_fling = true;
|
|
2230
|
+
let speed = 0;
|
|
2231
|
+
switch (this._DragInfo.Settings.DragDirection) {
|
|
2232
|
+
case Forge.DragSetting.DIRECTION_VERTICAL:
|
|
2233
|
+
distance_x = 0;
|
|
2234
|
+
if (distance_y === 0) {
|
|
2235
|
+
need_fling = false;
|
|
2236
|
+
}
|
|
2237
|
+
speed = Math.abs(event.velocityY);
|
|
2238
|
+
break;
|
|
2239
|
+
case Forge.DragSetting.DIRECTION_HORIZONTAL:
|
|
2240
|
+
distance_y = 0;
|
|
2241
|
+
if (distance_x === 0) {
|
|
2242
|
+
need_fling = false;
|
|
2243
|
+
}
|
|
2244
|
+
speed = Math.abs(event.velocityX);
|
|
2245
|
+
break;
|
|
2246
|
+
case Forge.DragSetting.DIRECTION_DISABLE:
|
|
2247
|
+
need_fling = false;
|
|
2248
|
+
break;
|
|
2249
|
+
default:
|
|
2250
|
+
speed = Math.sqrt(event.velocityX ** 2, event.velocityY ** 2);
|
|
2251
|
+
break;
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
if (need_fling) {
|
|
2255
|
+
event.deltaX = distance_x;
|
|
2256
|
+
event.deltaY = distance_y;
|
|
2257
|
+
this._DonFlingAnim(event, speed);
|
|
2258
|
+
}
|
|
2259
|
+
return true;
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
GetBoundingClientRect() {
|
|
2263
|
+
return new Promise((resolve, reject) => {
|
|
2264
|
+
if (this.Element) {
|
|
2265
|
+
//浏览器上仅为实现相似效果, 而style.animation设置后同一时间片内TransformAnimationObj还未创建,因此通过setTimeout保证TransformAnimationObj存在
|
|
2266
|
+
setTimeout(() => {
|
|
2267
|
+
let view = this;
|
|
2268
|
+
let animCount = 0;
|
|
2269
|
+
while(view) {
|
|
2270
|
+
if (view.TransformAnimationObj && view.TransformAnimationObj.repeatTimes > 0) {
|
|
2271
|
+
animCount++;
|
|
2272
|
+
view.TransformAnimationObj.AddAnimationListener(new Forge.AnimationListener(null, (normal_end) => {
|
|
2273
|
+
animCount--;
|
|
2274
|
+
if (animCount <= 0) {
|
|
2275
|
+
const {left, top, width, height} = this.Element.getBoundingClientRect();
|
|
2276
|
+
resolve({
|
|
2277
|
+
left,
|
|
2278
|
+
top,
|
|
2279
|
+
width,
|
|
2280
|
+
height,
|
|
2281
|
+
});
|
|
2282
|
+
}
|
|
2283
|
+
}));
|
|
2284
|
+
}
|
|
2285
|
+
view = view.ParentView;
|
|
2286
|
+
}
|
|
2287
|
+
}, 1);
|
|
2288
|
+
} else {
|
|
2289
|
+
reject(new Error("BrowserError: dom element is null."));
|
|
2290
|
+
}
|
|
2291
|
+
})
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
LayoutViewBase.DivId = 0;
|
|
2295
|
+
// Static variable
|
|
2296
|
+
Forge.LayoutViewBase = LayoutViewBase;
|
|
2297
|
+
|
|
2298
|
+
class LayoutView extends Forge.LayoutViewBase {
|
|
2299
|
+
/**
|
|
2300
|
+
* 渲染树的每个节点。<br>
|
|
2301
|
+
* 创建例子:<br>
|
|
2302
|
+
* 1. 通过Forge.TextureManager创建Texture<br>
|
|
2303
|
+
* 2. 将Texture装入Forge.TextureSetting集合, var ts = new Forge.TextureSetting(...);<br>
|
|
2304
|
+
* 3. var v = new Forge.LayoutView(ts)<br>
|
|
2305
|
+
* 4. 将view加入渲染树 parent_view.AddView(v, {x:0, y:0, width:100, height:100})<br>
|
|
2306
|
+
* width和height决定Texture的描画尺寸(拉伸)<br>
|
|
2307
|
+
*
|
|
2308
|
+
* @public
|
|
2309
|
+
* @constructor Forge.LayoutView
|
|
2310
|
+
* @extends Forge.LayoutViewBase
|
|
2311
|
+
* @param {Forge.TextureSetting} texture_setting 用于描画的Texture合集
|
|
2312
|
+
* */
|
|
2313
|
+
constructor(texture_setting, element_name) {
|
|
2314
|
+
if (texture_setting && !(texture_setting instanceof Forge.TextureSetting)) {
|
|
2315
|
+
Forge.ThrowError("ERROR:LayoutView need TextureSetting as parameter");
|
|
2316
|
+
}
|
|
2317
|
+
element_name = element_name || "div";
|
|
2318
|
+
super(texture_setting, element_name);
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
Forge.LayoutView = LayoutView;
|
|
2323
|
+
window.LayoutView = Forge.LayoutView; // export class
|
|
2324
|
+
class RootView extends Forge.LayoutView {
|
|
2325
|
+
/**
|
|
2326
|
+
* 根节点LayoutView
|
|
2327
|
+
*
|
|
2328
|
+
* @protected
|
|
2329
|
+
* @constructor Forge.RootView
|
|
2330
|
+
* @extends Forge.LayoutView
|
|
2331
|
+
* */
|
|
2332
|
+
constructor() {
|
|
2333
|
+
super(undefined, "root");
|
|
2334
|
+
this._ViewType = 1;
|
|
2335
|
+
this._IsChildOfRootView = true;
|
|
2336
|
+
window.gRootView = this;
|
|
2337
|
+
Forge.sRootView = this;
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2340
|
+
/**
|
|
2341
|
+
* 初始化RootView的尺寸(一般根据window.innerHeight和window.innerWidth)
|
|
2342
|
+
*
|
|
2343
|
+
* @public
|
|
2344
|
+
* @func Init
|
|
2345
|
+
* @memberof Forge.RootView
|
|
2346
|
+
* @instance
|
|
2347
|
+
* @param {Forge.Renderer} renderer
|
|
2348
|
+
* @param {int} left
|
|
2349
|
+
* @param {int} top
|
|
2350
|
+
* @param {int} width
|
|
2351
|
+
* @param {int} height
|
|
2352
|
+
* */
|
|
2353
|
+
Init(renderer, left, top, width, height) {
|
|
2354
|
+
// Init static private value
|
|
2355
|
+
this.InitLayoutViewStaticValues(renderer);
|
|
2356
|
+
|
|
2357
|
+
this.ResetLayoutParams({ x: 0, y: 0, width: 1280, height: 720 }); // TODO: 需要和ActivityManager设置进行对接
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
/**
|
|
2361
|
+
* 初始化LayoutViewBase中的静态变量
|
|
2362
|
+
*
|
|
2363
|
+
* @protected
|
|
2364
|
+
* @func InitLayoutViewStaticValues
|
|
2365
|
+
* @memberof Forge.LayoutViewBase
|
|
2366
|
+
* @instance
|
|
2367
|
+
* @param {Forge.Renderer} renderer
|
|
2368
|
+
* */
|
|
2369
|
+
InitLayoutViewStaticValues(renderer) {
|
|
2370
|
+
Forge.LayoutViewBase.sRenderer = renderer; // Set shared renderer of all LayoutView
|
|
2371
|
+
Forge.LayoutViewBase.sInternalTextureManager = renderer.GetSharedTextureManager();
|
|
2372
|
+
Forge.LayoutViewBase.sIdentityMat4 = new Forge.Mat4();
|
|
2373
|
+
Forge.LayoutViewBase.sNullDirectParentMat4 = new Forge.Mat4();
|
|
2374
|
+
Forge.LayoutViewBase.sBakeFlipYMat4 = new Forge.Mat4().rotatex(180);
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
Forge.RootView = RootView;
|
|
2378
|
+
window.RootView = Forge.RootView; // export class
|
|
2379
|
+
class CClipRectInfo {
|
|
2380
|
+
constructor(x, y, w, h, enable) {
|
|
2381
|
+
this.coordX = x;
|
|
2382
|
+
this.coordY = y;
|
|
2383
|
+
this.width = w;
|
|
2384
|
+
this.height = h;
|
|
2385
|
+
this.useScissors = enable;
|
|
2386
|
+
this.maskStencil = null;
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
updateInfo(x, y, w, h, enable) {
|
|
2390
|
+
this.coordX = x;
|
|
2391
|
+
this.coordY = y;
|
|
2392
|
+
this.width = w;
|
|
2393
|
+
this.height = h;
|
|
2394
|
+
this.useScissors = enable;
|
|
2395
|
+
}
|
|
2396
|
+
|
|
2397
|
+
setMaskStencil(local_file_uri) {
|
|
2398
|
+
this.maskStencil = local_file_uri;
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2402
|
+
class ClipView extends Forge.LayoutView {
|
|
2403
|
+
/**
|
|
2404
|
+
* 带裁剪功能的LayoutView
|
|
2405
|
+
*
|
|
2406
|
+
* @public
|
|
2407
|
+
* @constructor Forge.ClipView
|
|
2408
|
+
* @extends Forge.LayoutView
|
|
2409
|
+
* @param {Forge.TextureSetting} texture_setting 背景Texture集合
|
|
2410
|
+
* */
|
|
2411
|
+
constructor(texture_setting) {
|
|
2412
|
+
super(texture_setting, "div");
|
|
2413
|
+
this._ClipRectInfo = null;
|
|
2414
|
+
this.Id = "ClipView";
|
|
2415
|
+
this.TextureSetting = null;
|
|
2416
|
+
}
|
|
2417
|
+
|
|
2418
|
+
/**
|
|
2419
|
+
* 重载LayoutView.SetId,为所设置的Id添加后缀_ClipView
|
|
2420
|
+
*
|
|
2421
|
+
* @public
|
|
2422
|
+
* @func SetId
|
|
2423
|
+
* @memberof Forge.ClipView
|
|
2424
|
+
* @instance
|
|
2425
|
+
* @param {string} id 原始id
|
|
2426
|
+
* */
|
|
2427
|
+
SetId(id) {
|
|
2428
|
+
this.Id = `${id}_ClipView`;
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2431
|
+
/**
|
|
2432
|
+
* 设置裁剪区域大小
|
|
2433
|
+
*
|
|
2434
|
+
* @public
|
|
2435
|
+
* @func SetClipRect
|
|
2436
|
+
* @memberof Forge.ClipView
|
|
2437
|
+
* @instance
|
|
2438
|
+
* @param {int} x 相对于自己的坐标
|
|
2439
|
+
* @param {int} y 相对于自己的坐标
|
|
2440
|
+
* @param {int} width 相对于自己的坐标
|
|
2441
|
+
* @param {int} height 相对于自己的坐标
|
|
2442
|
+
* @param {boolean} use_scissors 是否进行裁剪
|
|
2443
|
+
* */
|
|
2444
|
+
SetClipRect(x, y, width, height, use_scissors) {
|
|
2445
|
+
// use_scissors = false; // Enabled only when debug
|
|
2446
|
+
if (this._ClipRectInfo === null) {
|
|
2447
|
+
this._ClipRectInfo = new CClipRectInfo(x, y, width, height, use_scissors);
|
|
2448
|
+
} else {
|
|
2449
|
+
this._ClipRectInfo.updateInfo(x, y, width, height, use_scissors);
|
|
2450
|
+
}
|
|
2451
|
+
const clip_left = x;
|
|
2452
|
+
const clip_top = y;
|
|
2453
|
+
const clip_right = this.LayoutParams.Width - clip_left - width;
|
|
2454
|
+
const clip_bottom = this.LayoutParams.Height - clip_top - height;
|
|
2455
|
+
if (use_scissors) {
|
|
2456
|
+
this.Element.style.overflow = "hidden";
|
|
2457
|
+
this.Element.style.clipPath = `inset(${clip_top}px ${clip_right}px ${clip_bottom}px ${clip_left}px)`;
|
|
2458
|
+
} else {
|
|
2459
|
+
this.Element.style.overflow = "visible";
|
|
2460
|
+
this.Element.style.clipPath = "unset";
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
Forge.ClipView = ClipView;
|
|
2465
|
+
window.ClipView = Forge.ClipView; // export class
|
|
2466
|
+
|
|
2467
|
+
class NinePatchView extends Forge.LayoutView {
|
|
2468
|
+
/**
|
|
2469
|
+
* 按照NinePatch方式进行渲染的专用LayoutView
|
|
2470
|
+
*
|
|
2471
|
+
* @public
|
|
2472
|
+
* @constructor Forge.NinePatchView
|
|
2473
|
+
* @extends Forge.LayoutView
|
|
2474
|
+
* @param {Forge.TextureSetting} texture_setting 背景Texture集合
|
|
2475
|
+
* */
|
|
2476
|
+
constructor(texture_setting) {
|
|
2477
|
+
super(texture_setting, "div");
|
|
2478
|
+
this._HorizontalRepeats = [0, 0, 0, 0];
|
|
2479
|
+
this._VerticalRepeats = [0, 0, 0, 0];
|
|
2480
|
+
this._HorizontalPadding = [0, 0];
|
|
2481
|
+
this._VerticalPadding = [0, 0];
|
|
2482
|
+
this._ImageDspWidth = 0;
|
|
2483
|
+
this._ImageDspHeight = 0;
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
/**
|
|
2487
|
+
* 设置新的Texture集合
|
|
2488
|
+
*
|
|
2489
|
+
* @public
|
|
2490
|
+
* @func ResetTexture
|
|
2491
|
+
* @memberof Forge.LayoutViewBase
|
|
2492
|
+
* @instance
|
|
2493
|
+
* @param {Forge.TextureSetting} texture_setting 新的Texture集合
|
|
2494
|
+
* */
|
|
2495
|
+
ResetTexture(texture_setting) {
|
|
2496
|
+
this.TextureSetting = texture_setting;
|
|
2497
|
+
this._ApplyChanges();
|
|
2498
|
+
}
|
|
2499
|
+
|
|
2500
|
+
/**
|
|
2501
|
+
* 设置横向延展区域和纵向延展的区域。(即NinePatch规则中的上边线和左边线)
|
|
2502
|
+
*
|
|
2503
|
+
* @public
|
|
2504
|
+
* @func SetRepeat
|
|
2505
|
+
* @memberof Forge.NinePatchView
|
|
2506
|
+
* @instance
|
|
2507
|
+
* @param {Array} horizontal_repeat 横向延展区域设置数组(目前延展区域个数最大支持2个)<br>
|
|
2508
|
+
* 数组元素内容,包含start和end该点:{start:xxx, width:xxx}
|
|
2509
|
+
* @param {Array} vertical_repeat 纵向延展区域设置数组(目前延展区域个数最大支持2个)<br>
|
|
2510
|
+
* 数组元素内容,包含start和end该点:{start:xxx, width:xxx}
|
|
2511
|
+
* */
|
|
2512
|
+
SetRepeat(horizontal_repeat, vertical_repeat) {
|
|
2513
|
+
Forge.Assert(horizontal_repeat.length <= 2);
|
|
2514
|
+
Forge.Assert(vertical_repeat.length <= 2);
|
|
2515
|
+
|
|
2516
|
+
for (let i = 0; i < 2; i++) {
|
|
2517
|
+
if (i < horizontal_repeat.length) {
|
|
2518
|
+
this._HorizontalRepeats[i * 2] = horizontal_repeat[i].start;
|
|
2519
|
+
this._HorizontalRepeats[i * 2 + 1] = horizontal_repeat[i].width;
|
|
2520
|
+
} else {
|
|
2521
|
+
this._HorizontalRepeats[i * 2] = 0;
|
|
2522
|
+
this._HorizontalRepeats[i * 2 + 1] = 0;
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2525
|
+
if (i < vertical_repeat.length) {
|
|
2526
|
+
this._VerticalRepeats[i * 2] = vertical_repeat[i].start;
|
|
2527
|
+
this._VerticalRepeats[i * 2 + 1] = vertical_repeat[i].width;
|
|
2528
|
+
} else {
|
|
2529
|
+
this._VerticalRepeats[i * 2] = 0;
|
|
2530
|
+
this._VerticalRepeats[i * 2 + 1] = 0;
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
this._ApplyChanges();
|
|
2535
|
+
|
|
2536
|
+
return this; // 为了支持连续设定的用法
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
/**
|
|
2540
|
+
* 设置横向填充区尺寸以及纵向填充区尺寸。(即NinePatch规则中的下边线和右边线)
|
|
2541
|
+
*
|
|
2542
|
+
* @public
|
|
2543
|
+
* @func SetPadding
|
|
2544
|
+
* @memberof Forge.NinePatchView
|
|
2545
|
+
* @instance
|
|
2546
|
+
* @param {Object} horizontal_padding 内容覆盖区域(横向),格式:{start:xxx, width:xxx}
|
|
2547
|
+
* @param {Object} vertical_padding 内容覆盖区域(纵向向),格式:{start:xxx, width:xxx}
|
|
2548
|
+
* */
|
|
2549
|
+
SetPadding(horizontal_padding, vertical_padding) {
|
|
2550
|
+
Forge.Assert(horizontal_padding !== null);
|
|
2551
|
+
Forge.Assert(vertical_padding !== null);
|
|
2552
|
+
this._VerticalPadding[0] = vertical_padding.start;
|
|
2553
|
+
this._VerticalPadding[1] = vertical_padding.width;
|
|
2554
|
+
this._HorizontalPadding[0] = horizontal_padding.start;
|
|
2555
|
+
this._HorizontalPadding[1] = horizontal_padding.width;
|
|
2556
|
+
|
|
2557
|
+
this._ApplyChanges();
|
|
2558
|
+
|
|
2559
|
+
return this; // 为了支持连续设定的用法
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2562
|
+
/**
|
|
2563
|
+
* 应对NinePatch图要缩放显示的场景,可以设置显示尺寸
|
|
2564
|
+
*
|
|
2565
|
+
* @public
|
|
2566
|
+
* @func SetImageDspSize
|
|
2567
|
+
* @memberof Forge.NinePatchView
|
|
2568
|
+
* @instance
|
|
2569
|
+
* @param {int} image_dsp_width 图片缩放后的显示宽度
|
|
2570
|
+
* @param {int} image_dsp_height 图片缩放后的显示高度
|
|
2571
|
+
* */
|
|
2572
|
+
SetImageDspSize(image_dsp_width, image_dsp_height) {
|
|
2573
|
+
this._ImageDspWidth = image_dsp_width;
|
|
2574
|
+
this._ImageDspHeight = image_dsp_height;
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2577
|
+
_ApplyChanges() {
|
|
2578
|
+
let texture_setting = this.TextureSetting;
|
|
2579
|
+
if (texture_setting) {
|
|
2580
|
+
if (texture_setting.MaskSetting) {
|
|
2581
|
+
if (texture_setting.MaskSetting._MaskType === "CORNER") {
|
|
2582
|
+
this._SetBorderRadius(texture_setting.MaskSetting);
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
if (texture_setting.Texture.Source) {
|
|
2586
|
+
const texture_width = texture_setting.Texture.RenderTexture.Width;
|
|
2587
|
+
const texture_height = texture_setting.Texture.RenderTexture.Height;
|
|
2588
|
+
const scale_width = texture_width / this._ImageDspWidth;
|
|
2589
|
+
const scale_height = texture_height / this._ImageDspHeight;
|
|
2590
|
+
|
|
2591
|
+
// image wide
|
|
2592
|
+
const wide_left = this._HorizontalRepeats[0];
|
|
2593
|
+
const wide_right = this._ImageDspWidth - this._HorizontalRepeats[1] - wide_left;
|
|
2594
|
+
const wide_top = this._VerticalRepeats[0];
|
|
2595
|
+
const wide_bottom = this._ImageDspHeight - this._VerticalRepeats[1] - wide_top;
|
|
2596
|
+
|
|
2597
|
+
// slice top right bottom left
|
|
2598
|
+
let slice_left = Math.floor(this._HorizontalRepeats[0] * scale_width);
|
|
2599
|
+
let slice_right =
|
|
2600
|
+
texture_width - Math.floor(this._HorizontalRepeats[1] * scale_width) - slice_left;
|
|
2601
|
+
let slice_top = Math.floor(this._VerticalRepeats[0] * scale_height);
|
|
2602
|
+
let slice_bottom =
|
|
2603
|
+
texture_height - Math.floor(this._VerticalRepeats[1] * scale_height) - slice_top;
|
|
2604
|
+
|
|
2605
|
+
if (slice_left + slice_right >= texture_width) {
|
|
2606
|
+
// 修正.9无中心repeat区域在PC repeat区域上不显示问题
|
|
2607
|
+
slice_left -= 1;
|
|
2608
|
+
slice_right -= 1;
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
if (slice_top + slice_bottom >= texture_height) {
|
|
2612
|
+
// 修正.9无中心repeat区域在PC repeat区域上不显示问题
|
|
2613
|
+
slice_top -= 1;
|
|
2614
|
+
slice_bottom -= 1;
|
|
2615
|
+
}
|
|
2616
|
+
|
|
2617
|
+
const slice_str = `${slice_top} ${slice_right} ${slice_bottom} ${slice_left}`;
|
|
2618
|
+
|
|
2619
|
+
// BorderImage
|
|
2620
|
+
this.Element.style.borderImage = `url(${texture_setting.Texture.Source}) ${slice_str} fill`; // 图片边框向内偏移。
|
|
2621
|
+
|
|
2622
|
+
// outset
|
|
2623
|
+
const outset_left = this._HorizontalPadding[0];
|
|
2624
|
+
const outset_right =
|
|
2625
|
+
this._ImageDspWidth - this._HorizontalPadding[1] - outset_left;
|
|
2626
|
+
const outset_top = this._VerticalPadding[0];
|
|
2627
|
+
const outset_bottom =
|
|
2628
|
+
this._ImageDspHeight - this._VerticalPadding[1] - outset_top;
|
|
2629
|
+
|
|
2630
|
+
this.Element.style.borderImageWidth = `${wide_top}px ${wide_right}px ${wide_bottom}px ${wide_left}px`; // 图片边框的宽度。
|
|
2631
|
+
this.Element.style.borderImageOutset = `${outset_top}px ${outset_right}px ${outset_bottom}px ${outset_left}px`; // 边框图像区域超出边框的量。
|
|
2632
|
+
}
|
|
2633
|
+
} else {
|
|
2634
|
+
// clear image set
|
|
2635
|
+
|
|
2636
|
+
// border radius
|
|
2637
|
+
this.Element.style.borderRadius = "";
|
|
2638
|
+
|
|
2639
|
+
// Border image
|
|
2640
|
+
this.Element.style.borderImage = "";
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
|
|
2645
|
+
Forge.NinePatchView = NinePatchView;
|
|
2646
|
+
|
|
2647
|
+
class JsvElementView extends Forge.LayoutView {
|
|
2648
|
+
/**
|
|
2649
|
+
* 根节点LayoutView
|
|
2650
|
+
*
|
|
2651
|
+
* @protected
|
|
2652
|
+
* @constructor Forge.RootView
|
|
2653
|
+
* @extends Forge.LayoutView
|
|
2654
|
+
* */
|
|
2655
|
+
constructor(name) {
|
|
2656
|
+
let origin_name;
|
|
2657
|
+
if (name.startsWith("jsve-")) {
|
|
2658
|
+
// 新模式 jsve-XXXX 避免和vue的普通定义重名
|
|
2659
|
+
origin_name = name.substr(5);
|
|
2660
|
+
} else {
|
|
2661
|
+
// 兼容老版本的 jsvXXX 模式
|
|
2662
|
+
origin_name = name.substr(3);
|
|
2663
|
+
}
|
|
2664
|
+
super(undefined, origin_name);
|
|
2665
|
+
}
|
|
2666
|
+
|
|
2667
|
+
setAttribute(name, value) {
|
|
2668
|
+
this.Element.setAttribute(name, value);
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
removeAttribute(name) {
|
|
2672
|
+
this.Element.removeAttribute(name);
|
|
2673
|
+
}
|
|
2674
|
+
|
|
2675
|
+
getAttribute(name) {
|
|
2676
|
+
return this.Element.getAttribute(name);
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2679
|
+
hasAttribute(name) {
|
|
2680
|
+
return this.Element.hasAttribute(name);
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2683
|
+
get textContent() {
|
|
2684
|
+
return this.Element.textContent;
|
|
2685
|
+
}
|
|
2686
|
+
|
|
2687
|
+
set textContent(text) {
|
|
2688
|
+
this.Element.textContent = text;
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
Forge.JsvElementView = JsvElementView;
|
|
2692
|
+
|
|
2693
|
+
class VideoView extends Forge.LayoutView {
|
|
2694
|
+
constructor(video_player_hdl, texture_setting) {
|
|
2695
|
+
super(texture_setting);
|
|
2696
|
+
this._ViewType = 8;
|
|
2697
|
+
this.Element = video_player_hdl.Ele;
|
|
2698
|
+
this.Id = "VideoView";
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
/**
|
|
2702
|
+
* 重载LayoutView.SetId,为所设置的Id添加后缀_VideoView
|
|
2703
|
+
*
|
|
2704
|
+
* @public
|
|
2705
|
+
* @func SetId
|
|
2706
|
+
* @memberof Forge.VideoView
|
|
2707
|
+
* @instance
|
|
2708
|
+
* @param {string} id 原始id
|
|
2709
|
+
* */
|
|
2710
|
+
SetId(id) {
|
|
2711
|
+
this.Id = `${id}_VideoView`;
|
|
2712
|
+
}
|
|
2713
|
+
|
|
2714
|
+
ResetLayoutParams(new_params) {
|
|
2715
|
+
if (new_params !== null) {
|
|
2716
|
+
if (!(new_params instanceof Forge.LayoutParamsBase)) {
|
|
2717
|
+
this.LayoutParams = new Forge.LayoutParams(new_params);
|
|
2718
|
+
} else {
|
|
2719
|
+
this.LayoutParams = new_params.Clone();
|
|
2720
|
+
}
|
|
2721
|
+
this.Element.style.left = `${this.LayoutParams.MarginLeft}px`;
|
|
2722
|
+
this.Element.style.top = `${this.LayoutParams.MarginTop}px`;
|
|
2723
|
+
if (this.LayoutParams.Width) {
|
|
2724
|
+
this.Element.style.width = `${this.LayoutParams.Width}px`;
|
|
2725
|
+
}
|
|
2726
|
+
if (this.LayoutParams.Height) {
|
|
2727
|
+
this.Element.style.height = `${this.LayoutParams.Height}px`;
|
|
2728
|
+
}
|
|
2729
|
+
} else {
|
|
2730
|
+
Forge.ThrowError("ResetLayoutParams(): new params is null");
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2733
|
+
|
|
2734
|
+
_OnDetachFromSystem() {
|
|
2735
|
+
super._OnDetachFromSystem();
|
|
2736
|
+
if (this._VideoPlayerHdl) {
|
|
2737
|
+
this._VideoPlayerHdl.unload();
|
|
2738
|
+
this._VideoPlayerHdl = null;
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2742
|
+
Forge.VideoView = VideoView;
|
|
2743
|
+
|
|
2744
|
+
class EditControlView extends Forge.LayoutView {
|
|
2745
|
+
/**
|
|
2746
|
+
* 带输入框功能的LayoutView
|
|
2747
|
+
*
|
|
2748
|
+
* @constructor Forge.EditControlView
|
|
2749
|
+
* @extends Forge.LayoutView
|
|
2750
|
+
* @param {Forge.TextureSetting} texture_setting 背景Texture集合
|
|
2751
|
+
* */
|
|
2752
|
+
constructor() {
|
|
2753
|
+
super(null, "input");
|
|
2754
|
+
this._ViewType = 5;
|
|
2755
|
+
this._InputType = Forge.TextInputType.TEXT;
|
|
2756
|
+
this.Id = "EditControlView";
|
|
2757
|
+
}
|
|
2758
|
+
|
|
2759
|
+
_OnAttachToSystem() {
|
|
2760
|
+
super._OnAttachToSystem();
|
|
2761
|
+
// 该input只作为文字录入的辅助作用,故移除屏幕外,
|
|
2762
|
+
// 具体描画为高阶控件操控
|
|
2763
|
+
this.Element.style.left = "-1920px";
|
|
2764
|
+
this.Element.style.top = "-1080px";
|
|
2765
|
+
this.Element.style.width = "1px";
|
|
2766
|
+
this.Element.style.height = "1px";
|
|
2767
|
+
/* //TODO for Test
|
|
2768
|
+
this.Element.style.left="300px";
|
|
2769
|
+
this.Element.style.top="100px";
|
|
2770
|
+
this.Element.style.width="100px";
|
|
2771
|
+
this.Element.style.height="50px"; */
|
|
2772
|
+
|
|
2773
|
+
// pointerEvents设置,input才能获得焦点
|
|
2774
|
+
this.Element.style.pointerEvents = "auto";
|
|
2775
|
+
this.Element.addEventListener("keydown", (event) => {
|
|
2776
|
+
// add listener keydown for textarea
|
|
2777
|
+
event = event || window.event;
|
|
2778
|
+
let cur_offset = this.Element.selectionStart;
|
|
2779
|
+
console.log(`keydown cur_offset:${cur_offset}`);
|
|
2780
|
+
if (event.keyCode === 37) {
|
|
2781
|
+
--cur_offset;
|
|
2782
|
+
if (cur_offset < 0) {
|
|
2783
|
+
cur_offset = 0;
|
|
2784
|
+
}
|
|
2785
|
+
if (cur_offset !== this.Element.selectionStart) {
|
|
2786
|
+
this.OnTextChanged(this.Element.value, cur_offset, true);
|
|
2787
|
+
if (event.stopPropagation) {
|
|
2788
|
+
event.stopPropagation();
|
|
2789
|
+
}
|
|
2790
|
+
} else {
|
|
2791
|
+
this.Element.blur();
|
|
2792
|
+
}
|
|
2793
|
+
} else if (event.keyCode === 39) {
|
|
2794
|
+
++cur_offset;
|
|
2795
|
+
if (cur_offset > this.Element.value.length) {
|
|
2796
|
+
cur_offset = this.Element.value.length;
|
|
2797
|
+
}
|
|
2798
|
+
if (cur_offset !== this.Element.selectionStart) {
|
|
2799
|
+
this.OnTextChanged(this.Element.value, cur_offset, true);
|
|
2800
|
+
if (event.stopPropagation) {
|
|
2801
|
+
event.stopPropagation();
|
|
2802
|
+
}
|
|
2803
|
+
} else {
|
|
2804
|
+
this.Element.blur();
|
|
2805
|
+
}
|
|
2806
|
+
} else if (event.keyCode === 38 || event.keyCode === 40) {
|
|
2807
|
+
this.Element.blur();
|
|
2808
|
+
}
|
|
2809
|
+
});
|
|
2810
|
+
|
|
2811
|
+
// input onfocus焦点获得
|
|
2812
|
+
this.Element.onfocus = (event) => {
|
|
2813
|
+
console.log("onfocus in");
|
|
2814
|
+
this.OnStatusChanged(1);
|
|
2815
|
+
};
|
|
2816
|
+
// input onfocus焦点丢失
|
|
2817
|
+
this.Element.onblur = (event) => {
|
|
2818
|
+
console.log("onblur in");
|
|
2819
|
+
this.OnStatusChanged(0);
|
|
2820
|
+
};
|
|
2821
|
+
const ifDigital = (char) =>
|
|
2822
|
+
"0".charCodeAt() <= char.charCodeAt() &&
|
|
2823
|
+
char.charCodeAt() <= "9".charCodeAt();
|
|
2824
|
+
|
|
2825
|
+
// input 文字变化时
|
|
2826
|
+
this.Element.oninput = (event) => {
|
|
2827
|
+
console.log("oninput:", event);
|
|
2828
|
+
if (event.target.value.length > 0 && event.target.selectionStart > 0) {
|
|
2829
|
+
const start = event.target.selectionStart - 1;
|
|
2830
|
+
const end = event.target.selectionStart;
|
|
2831
|
+
const add_text = event.target.value.slice(start, end);
|
|
2832
|
+
if (
|
|
2833
|
+
!ifDigital(add_text) &&
|
|
2834
|
+
this._InputType === Forge.TextInputType.NUMBER
|
|
2835
|
+
) {
|
|
2836
|
+
event.target.value =
|
|
2837
|
+
event.target.value.substr(0, start) +
|
|
2838
|
+
event.target.value.substr(end);
|
|
2839
|
+
event.target.selectionStart = start;
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
|
|
2843
|
+
const text = event.target.value;
|
|
2844
|
+
const select_start = event.target.selectionStart;
|
|
2845
|
+
this.OnTextChanged(decodeURIComponent(text), select_start);
|
|
2846
|
+
};
|
|
2847
|
+
}
|
|
2848
|
+
|
|
2849
|
+
/**
|
|
2850
|
+
* 重载LayoutView.SetId,为所设置的Id添加后缀_EditControlView
|
|
2851
|
+
*
|
|
2852
|
+
* @public
|
|
2853
|
+
* @func SetId
|
|
2854
|
+
* @memberof Forge.EditControlView
|
|
2855
|
+
* @instance
|
|
2856
|
+
* @param {string} id 原始id
|
|
2857
|
+
* */
|
|
2858
|
+
SetId(id) {
|
|
2859
|
+
this.Id = `${id}_EditControlView`;
|
|
2860
|
+
}
|
|
2861
|
+
|
|
2862
|
+
/**
|
|
2863
|
+
* 显示输入法
|
|
2864
|
+
*
|
|
2865
|
+
* @public
|
|
2866
|
+
* @func showIme
|
|
2867
|
+
* @memberof Forge.EditControlView
|
|
2868
|
+
* @instance
|
|
2869
|
+
* @param {Forge.TextInputType} input_type
|
|
2870
|
+
* @param {string} text 显示字符串
|
|
2871
|
+
* @param {int} cursor_pos 光标所在位置
|
|
2872
|
+
* @param {int} selectionEnd 字符串选择stop位置,默认为文字的末尾
|
|
2873
|
+
* */
|
|
2874
|
+
showIme(input_type, text, cursor_pos) {
|
|
2875
|
+
if (!this.Element) {
|
|
2876
|
+
console.log("showIme but ele is null!");
|
|
2877
|
+
return;
|
|
2878
|
+
}
|
|
2879
|
+
if (input_type === Forge.TextInputType.NONE) {
|
|
2880
|
+
console.log("showIme input_type error");
|
|
2881
|
+
return;
|
|
2882
|
+
}
|
|
2883
|
+
if (typeof cursor_pos === "undefined" || cursor_pos === null) {
|
|
2884
|
+
cursor_pos = text.length > 0 ? text.length : 0;
|
|
2885
|
+
}
|
|
2886
|
+
if (cursor_pos < 0) {
|
|
2887
|
+
cursor_pos = 0;
|
|
2888
|
+
} else if (cursor_pos > text.length) {
|
|
2889
|
+
cursor_pos = text.length > 0 ? text.length : 0;
|
|
2890
|
+
}
|
|
2891
|
+
this._InputType = input_type;
|
|
2892
|
+
/* switch (input_type) {
|
|
2893
|
+
case Forge.TextInputType.PASSWORD:
|
|
2894
|
+
this.Element.type = "password";
|
|
2895
|
+
break;
|
|
2896
|
+
case Forge.TextInputType.NUMBER:
|
|
2897
|
+
this.Element.type = "number";
|
|
2898
|
+
break;
|
|
2899
|
+
case Forge.TextInputType.TEXT:
|
|
2900
|
+
default:
|
|
2901
|
+
this.Element.type = "text";
|
|
2902
|
+
break;
|
|
2903
|
+
} */
|
|
2904
|
+
// 浏览器端不对type做限制,(因为number/password类型时selectionStart为null)
|
|
2905
|
+
this.Element.type = "text";
|
|
2906
|
+
this.Element.value = text;
|
|
2907
|
+
this.Element.focus();
|
|
2908
|
+
this.Element.selectionStart = cursor_pos;
|
|
2909
|
+
this.Element.selectionEnd = cursor_pos;
|
|
2910
|
+
}
|
|
2911
|
+
|
|
2912
|
+
/**
|
|
2913
|
+
* 隐藏输入法
|
|
2914
|
+
*
|
|
2915
|
+
* @public
|
|
2916
|
+
* @func hideIme
|
|
2917
|
+
* @memberof Forge.EditControlView
|
|
2918
|
+
* @instance
|
|
2919
|
+
* */
|
|
2920
|
+
hideIme() {
|
|
2921
|
+
if (!this.Element) {
|
|
2922
|
+
console.log("hideIme, but ele is null!");
|
|
2923
|
+
return;
|
|
2924
|
+
}
|
|
2925
|
+
this.Element.blur();
|
|
2926
|
+
}
|
|
2927
|
+
|
|
2928
|
+
/**
|
|
2929
|
+
* 更新光标位置
|
|
2930
|
+
*
|
|
2931
|
+
* @public
|
|
2932
|
+
* @func updateCursorOffset
|
|
2933
|
+
* @memberof Forge.EditControlView
|
|
2934
|
+
*
|
|
2935
|
+
* @instance
|
|
2936
|
+
* @param {String} text 显示字符串
|
|
2937
|
+
* @param {int} cursor_pos 光标所在位置
|
|
2938
|
+
* */
|
|
2939
|
+
updateCursorOffset(text, cursor_offset) {
|
|
2940
|
+
if (!this.Element) {
|
|
2941
|
+
console.log("updateCursorOffset, but ele is null!");
|
|
2942
|
+
return;
|
|
2943
|
+
}
|
|
2944
|
+
this.Element.selectionStart = cursor_offset;
|
|
2945
|
+
this.Element.selectionEnd = cursor_offset;
|
|
2946
|
+
this.Element.value = text;
|
|
2947
|
+
}
|
|
2948
|
+
|
|
2949
|
+
/**
|
|
2950
|
+
* 文字变更
|
|
2951
|
+
* @param value
|
|
2952
|
+
* @param {int} cursor_pos 光标所在位置
|
|
2953
|
+
* @param {bool} moved 光标移动
|
|
2954
|
+
* @constructor
|
|
2955
|
+
*/
|
|
2956
|
+
OnTextChanged(value, cursor_pos, moved) {
|
|
2957
|
+
// Override
|
|
2958
|
+
console.log(`OnTextChanged value:${value}`);
|
|
2959
|
+
}
|
|
2960
|
+
|
|
2961
|
+
/**
|
|
2962
|
+
* 状态变更
|
|
2963
|
+
* @param status 输入法状态 1:'show'/0:'hide'
|
|
2964
|
+
* @constructor
|
|
2965
|
+
*/
|
|
2966
|
+
OnStatusChanged(status) {
|
|
2967
|
+
// Override
|
|
2968
|
+
}
|
|
2969
|
+
|
|
2970
|
+
/**
|
|
2971
|
+
* action 事件通知
|
|
2972
|
+
* @param action
|
|
2973
|
+
* @constructor
|
|
2974
|
+
*/
|
|
2975
|
+
OnEditAction(action) {
|
|
2976
|
+
// Override
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
|
|
2980
|
+
class FilterView extends Forge.LayoutView {
|
|
2981
|
+
constructor(texture_setting, type = 1) {
|
|
2982
|
+
super(texture_setting);
|
|
2983
|
+
this._ViewType = 10;
|
|
2984
|
+
this._FilterType = type
|
|
2985
|
+
this.Id = "FilterView";
|
|
2986
|
+
this.Element.style.filter = "grayscale(100%)"
|
|
2987
|
+
}
|
|
2988
|
+
FilterSwitch(enable) {
|
|
2989
|
+
if (this.Element) {
|
|
2990
|
+
this.Element.style.filter = enable ? "grayscale(100%)" : "";
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
SetId(id) {
|
|
2994
|
+
this.Id = id + "_FilterView";
|
|
2995
|
+
}
|
|
2996
|
+
}
|
|
2997
|
+
Forge.FilterView = FilterView;
|
|
2998
|
+
|
|
2999
|
+
Forge.TextInputType = {
|
|
3000
|
+
NONE: 0,
|
|
3001
|
+
TEXT: 1,
|
|
3002
|
+
PASSWORD: 2,
|
|
3003
|
+
TEXT_AREA: 3,
|
|
3004
|
+
CONTENT_EDITABLE: 4,
|
|
3005
|
+
SEARCH: 5,
|
|
3006
|
+
URL: 6,
|
|
3007
|
+
EMAIL: 7,
|
|
3008
|
+
TELEPHONE: 8,
|
|
3009
|
+
NUMBER: 9,
|
|
3010
|
+
};
|
|
3011
|
+
Forge.EditControlView = EditControlView;
|
|
3012
|
+
class JsvControl {
|
|
3013
|
+
constructor(params_count) {
|
|
3014
|
+
this._Current = new Array(params_count).fill(0);
|
|
3015
|
+
this._Target = new Array(params_count).fill(0);
|
|
3016
|
+
this._RepeatStart = new Array(params_count).fill(0);
|
|
3017
|
+
this._JumpTarget = null;
|
|
3018
|
+
this._Jumping = false;
|
|
3019
|
+
this._ParameterCount = params_count;
|
|
3020
|
+
this._StateIndex = 0; // 0: idle, 1:running
|
|
3021
|
+
this._StateLocked = false;
|
|
3022
|
+
this._StartSwitcher = false;
|
|
3023
|
+
this._PausedCallback = null;
|
|
3024
|
+
this._EndCallback = null;
|
|
3025
|
+
this._NextEndCallback = null;
|
|
3026
|
+
this._Token = 0;
|
|
3027
|
+
this._Repeat = false;
|
|
3028
|
+
this._OnRepeatCallback = null;
|
|
3029
|
+
this._SpriteView = null;
|
|
3030
|
+
this._AdvanceCallback = null;
|
|
3031
|
+
}
|
|
3032
|
+
|
|
3033
|
+
setRepeat(enable, repeat_callback) {
|
|
3034
|
+
this._Repeat = enable;
|
|
3035
|
+
if (enable) {
|
|
3036
|
+
this._OnRepeatCallback = repeat_callback;
|
|
3037
|
+
} else {
|
|
3038
|
+
this._OnRepeatCallback = null;
|
|
3039
|
+
}
|
|
3040
|
+
return this;
|
|
3041
|
+
}
|
|
3042
|
+
|
|
3043
|
+
start(end_callback, advance_callback) {
|
|
3044
|
+
// 取消旧的Callback
|
|
3045
|
+
this._NextEndCallback = end_callback;
|
|
3046
|
+
this._EndCallback = null;
|
|
3047
|
+
this._AdvanceCallback = advance_callback;
|
|
3048
|
+
this._StartSwitcher = true;
|
|
3049
|
+
this._Jumping = false;
|
|
3050
|
+
this._StateMachineNext();
|
|
3051
|
+
}
|
|
3052
|
+
|
|
3053
|
+
pause(paused_callback) {
|
|
3054
|
+
this._AdvanceCallback = null;
|
|
3055
|
+
|
|
3056
|
+
// 执行pause动作时,相当于取消start()动作,所以EndCallback同时也应该被取消
|
|
3057
|
+
if (this._EndCallback !== null || this._NextEndCallback !== null) {
|
|
3058
|
+
this._EndCallback = null;
|
|
3059
|
+
this._NextEndCallback = null;
|
|
3060
|
+
}
|
|
3061
|
+
|
|
3062
|
+
// 根据当前状态,已经处于Pause则直接回调,否则发送pause指令
|
|
3063
|
+
if (this._StateIndex === 0) {
|
|
3064
|
+
if (paused_callback) {
|
|
3065
|
+
this._CallbackWithCatch(this._Current, paused_callback);
|
|
3066
|
+
}
|
|
3067
|
+
} else {
|
|
3068
|
+
if (paused_callback) {
|
|
3069
|
+
this._PausedCallback = paused_callback;
|
|
3070
|
+
}
|
|
3071
|
+
this._StateMachineNext();
|
|
3072
|
+
}
|
|
3073
|
+
}
|
|
3074
|
+
|
|
3075
|
+
jump() {
|
|
3076
|
+
this._JumpTarget = [...this._Target];
|
|
3077
|
+
this._Jumping = true;
|
|
3078
|
+
this._StartSwitcher = true;
|
|
3079
|
+
this._StateMachineNext();
|
|
3080
|
+
}
|
|
3081
|
+
|
|
3082
|
+
jumpSilent() {
|
|
3083
|
+
this._JumpTarget = [...this._Target];
|
|
3084
|
+
}
|
|
3085
|
+
|
|
3086
|
+
startFpsTesting() {
|
|
3087
|
+
Forge.sRenderBridge.SetStepFpsSwitch(true);
|
|
3088
|
+
}
|
|
3089
|
+
|
|
3090
|
+
stopFpsTesting() {
|
|
3091
|
+
Forge.sRenderBridge.SetStepFpsSwitch(false);
|
|
3092
|
+
}
|
|
3093
|
+
|
|
3094
|
+
_WrapBuildAnimation(repeat_start_array, current_array, tos_array, act_jump) {
|
|
3095
|
+
console.warn("Should Override");
|
|
3096
|
+
}
|
|
3097
|
+
|
|
3098
|
+
_WrapCallback(currents, callback) {
|
|
3099
|
+
console.warn("Should Override");
|
|
3100
|
+
}
|
|
3101
|
+
|
|
3102
|
+
_CallbackWithCatch(currents, callback) {
|
|
3103
|
+
try {
|
|
3104
|
+
this._WrapCallback(currents, callback);
|
|
3105
|
+
} catch (e) {
|
|
3106
|
+
console.error("Error:in callback");
|
|
3107
|
+
console.error(e);
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
|
|
3111
|
+
_StateMachineNext() {
|
|
3112
|
+
if (this._StateLocked) {
|
|
3113
|
+
// 内部处理进行中,暂停状态切换
|
|
3114
|
+
return;
|
|
3115
|
+
}
|
|
3116
|
+
|
|
3117
|
+
if (this._StateIndex === 0) {
|
|
3118
|
+
// Idle -> play, need switcher
|
|
3119
|
+
if (this._StartSwitcher) {
|
|
3120
|
+
this._StartSwitcher = false;
|
|
3121
|
+
if (this._StartAnimation()) {
|
|
3122
|
+
this._StateIndex = 1;
|
|
3123
|
+
}
|
|
3124
|
+
}
|
|
3125
|
+
} else if (this._StateIndex === 1) {
|
|
3126
|
+
// Play -> idle, no need switcher
|
|
3127
|
+
this._StopAnimation();
|
|
3128
|
+
}
|
|
3129
|
+
}
|
|
3130
|
+
|
|
3131
|
+
_StartAnimation() {
|
|
3132
|
+
// 当动画开始后才进行回调设置,防止Pause过程中直接调用了新设置进的回调
|
|
3133
|
+
this._EndCallback = this._NextEndCallback;
|
|
3134
|
+
this._NextEndCallback = null;
|
|
3135
|
+
|
|
3136
|
+
const froms = this._JumpTarget ? [...this._JumpTarget] : [...this._Current];
|
|
3137
|
+
const tos = this._Target;
|
|
3138
|
+
const repeat_starts = this._Repeat ? [...this._RepeatStart] : null;
|
|
3139
|
+
|
|
3140
|
+
// const token = this._Token++;
|
|
3141
|
+
|
|
3142
|
+
const anim = this._WrapBuildAnimation(
|
|
3143
|
+
repeat_starts,
|
|
3144
|
+
froms,
|
|
3145
|
+
tos,
|
|
3146
|
+
this._Jumping
|
|
3147
|
+
);
|
|
3148
|
+
|
|
3149
|
+
// clear jump status
|
|
3150
|
+
this._JumpTarget = null;
|
|
3151
|
+
this._Jumping = false;
|
|
3152
|
+
|
|
3153
|
+
if (anim === null) {
|
|
3154
|
+
return;
|
|
3155
|
+
}
|
|
3156
|
+
|
|
3157
|
+
// 生成OnFinalProgress处理监听,memo在 _WrapBuildAnimation()处理后生成,因为build处理中可能改变tos
|
|
3158
|
+
const memo_tos = [...tos];
|
|
3159
|
+
const that = this;
|
|
3160
|
+
const listener = new Forge.AnimationListener()
|
|
3161
|
+
.OnFinalProgress((progress) => {
|
|
3162
|
+
that._OnPaused(
|
|
3163
|
+
repeat_starts !== null ? repeat_starts : froms,
|
|
3164
|
+
memo_tos,
|
|
3165
|
+
progress
|
|
3166
|
+
);
|
|
3167
|
+
})
|
|
3168
|
+
.OnAdvance((progress) => {
|
|
3169
|
+
if (this._AdvanceCallback) {
|
|
3170
|
+
this._AdvanceCallback(progress);
|
|
3171
|
+
}
|
|
3172
|
+
});
|
|
3173
|
+
|
|
3174
|
+
if (this._OnRepeatCallback) {
|
|
3175
|
+
listener.OnRepeat((times) => {
|
|
3176
|
+
if (that._OnRepeatCallback) {
|
|
3177
|
+
that._OnRepeatCallback(times);
|
|
3178
|
+
}
|
|
3179
|
+
});
|
|
3180
|
+
}
|
|
3181
|
+
|
|
3182
|
+
anim.AddAnimationListener(listener);
|
|
3183
|
+
anim.Enable(Forge.AnimationEnable.KeepTransform);
|
|
3184
|
+
if (this._Repeat) {
|
|
3185
|
+
anim.EnableInfinite();
|
|
3186
|
+
}
|
|
3187
|
+
this._SpriteView.StartAnimation(anim);
|
|
3188
|
+
|
|
3189
|
+
return true; // success
|
|
3190
|
+
}
|
|
3191
|
+
|
|
3192
|
+
_StopAnimation() {
|
|
3193
|
+
this._SpriteView.StopAnimation();
|
|
3194
|
+
}
|
|
3195
|
+
|
|
3196
|
+
_OnPaused(froms, tos, progress) {
|
|
3197
|
+
for (let i = 0; i < this._ParameterCount; i++) {
|
|
3198
|
+
this._Current[i] = Math.floor((tos[i] - froms[i]) * progress + froms[i]);
|
|
3199
|
+
}
|
|
3200
|
+
|
|
3201
|
+
this._StateLocked = true;
|
|
3202
|
+
// 换出callbacks,回调时可能加入新的callbacks
|
|
3203
|
+
const paused_callback = this._PausedCallback;
|
|
3204
|
+
const ended_callback = this._EndCallback;
|
|
3205
|
+
this._PausedCallback = null;
|
|
3206
|
+
|
|
3207
|
+
// 回调所有callback
|
|
3208
|
+
if (paused_callback) {
|
|
3209
|
+
// Paused callback
|
|
3210
|
+
this._CallbackWithCatch(this._Current, paused_callback);
|
|
3211
|
+
}
|
|
3212
|
+
if (ended_callback && progress === 1) {
|
|
3213
|
+
// Ended callback
|
|
3214
|
+
this._EndCallback = null;
|
|
3215
|
+
this._CallbackWithCatch(this._Current, ended_callback);
|
|
3216
|
+
}
|
|
3217
|
+
|
|
3218
|
+
this._StateLocked = false;
|
|
3219
|
+
|
|
3220
|
+
this._StateIndex = 0; // mark idle
|
|
3221
|
+
const that = this;
|
|
3222
|
+
that._StateMachineNext(); // Trigger next start
|
|
3223
|
+
}
|
|
3224
|
+
|
|
3225
|
+
_SetView(jsv_view) {
|
|
3226
|
+
this._SpriteView = jsv_view;
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
class DragTranslateControl extends JsvControl {
|
|
3230
|
+
constructor() {
|
|
3231
|
+
super(2); // targetX, targetY, accelerate, init velocity
|
|
3232
|
+
this._Mode = 0; // 0: 匀速控制模式, 1: 加减速控制模式
|
|
3233
|
+
this._Speed = 0; // pixel per second
|
|
3234
|
+
this._VerlocityAcc = 0; // 加速度值
|
|
3235
|
+
this._VerlocityInit = 0; // 初始速度
|
|
3236
|
+
this._AccAlongX = true; // true 延X轴加速, false 延Y轴加速
|
|
3237
|
+
this._AnimationRef = null;
|
|
3238
|
+
this._AllowFrameStep = false; // 是否可以使用FrameStep模式,该模式下为了保证动画的平滑性,动画总运行时间会超过设定时间
|
|
3239
|
+
}
|
|
3240
|
+
|
|
3241
|
+
allowFrameStepMode(allow) {
|
|
3242
|
+
this._AllowFrameStep = allow;
|
|
3243
|
+
return this;
|
|
3244
|
+
}
|
|
3245
|
+
|
|
3246
|
+
selectMode(mode) {
|
|
3247
|
+
switch (mode) {
|
|
3248
|
+
case "UniformMotion":
|
|
3249
|
+
this._Mode = 0;
|
|
3250
|
+
break;
|
|
3251
|
+
case "AcceleratedMotion":
|
|
3252
|
+
this._Mode = 1;
|
|
3253
|
+
this.setRepeat(false); // 加速模式不支持repeat
|
|
3254
|
+
break;
|
|
3255
|
+
default:
|
|
3256
|
+
console.error(`Unsupported input=${mode}`);
|
|
3257
|
+
}
|
|
3258
|
+
|
|
3259
|
+
return this;
|
|
3260
|
+
}
|
|
3261
|
+
|
|
3262
|
+
targetX(new_x) {
|
|
3263
|
+
// Take effect in next Start
|
|
3264
|
+
this._Target[0] = new_x;
|
|
3265
|
+
return this;
|
|
3266
|
+
}
|
|
3267
|
+
|
|
3268
|
+
targetY(new_y) {
|
|
3269
|
+
// Take effect in next Start
|
|
3270
|
+
this._Target[1] = new_y;
|
|
3271
|
+
return this;
|
|
3272
|
+
}
|
|
3273
|
+
|
|
3274
|
+
target(new_x, new_y) {
|
|
3275
|
+
// Take effect in next Start
|
|
3276
|
+
this._Target[0] = new_x;
|
|
3277
|
+
this._Target[1] = new_y;
|
|
3278
|
+
return this;
|
|
3279
|
+
}
|
|
3280
|
+
|
|
3281
|
+
// start_x, start_y,必须要在当前位置到target的范围之外,范围之内目前不支持
|
|
3282
|
+
enableRepeatFrom(start_x, start_y, repeat_callback) {
|
|
3283
|
+
if (!this._ComfirmMode(0)) return;
|
|
3284
|
+
|
|
3285
|
+
this.setRepeat(true, repeat_callback);
|
|
3286
|
+
this._RepeatStart[0] = start_x;
|
|
3287
|
+
this._RepeatStart[1] = start_y;
|
|
3288
|
+
return this;
|
|
3289
|
+
}
|
|
3290
|
+
|
|
3291
|
+
speed(pixel_per_second) {
|
|
3292
|
+
console.log(`speed, pixel_per_second:${pixel_per_second}`);
|
|
3293
|
+
if (!this._ComfirmMode(0)) return;
|
|
3294
|
+
|
|
3295
|
+
// Take effect in next Start
|
|
3296
|
+
this._Speed = pixel_per_second;
|
|
3297
|
+
return this;
|
|
3298
|
+
}
|
|
3299
|
+
|
|
3300
|
+
// Start后,从当前位置到目标位置后动画结束
|
|
3301
|
+
accelerateX(acc_x, target_x) {
|
|
3302
|
+
if (!this._ComfirmMode(1)) return;
|
|
3303
|
+
|
|
3304
|
+
this._Target[0] = target_x;
|
|
3305
|
+
this._VerlocityAcc = acc_x;
|
|
3306
|
+
this._VerlocityInit = 0;
|
|
3307
|
+
this._AccAlongX = true;
|
|
3308
|
+
return this;
|
|
3309
|
+
}
|
|
3310
|
+
|
|
3311
|
+
accelerateY(acc_y, target_y) {
|
|
3312
|
+
if (!this._ComfirmMode(1)) return;
|
|
3313
|
+
|
|
3314
|
+
this._Target[1] = target_y;
|
|
3315
|
+
this._VerlocityAcc = acc_y;
|
|
3316
|
+
this._VerlocityInit = 0;
|
|
3317
|
+
this._AccAlongX = false;
|
|
3318
|
+
return this;
|
|
3319
|
+
}
|
|
3320
|
+
|
|
3321
|
+
decelerateX(acc_x, init_v_x) {
|
|
3322
|
+
if (!this._ComfirmMode(1)) return;
|
|
3323
|
+
|
|
3324
|
+
this._VerlocityAcc = acc_x;
|
|
3325
|
+
this._VerlocityInit = init_v_x;
|
|
3326
|
+
this._AccAlongX = true;
|
|
3327
|
+
return this;
|
|
3328
|
+
}
|
|
3329
|
+
|
|
3330
|
+
decelerateY(acc_y, init_v_y) {
|
|
3331
|
+
if (!this._ComfirmMode(1)) return;
|
|
3332
|
+
|
|
3333
|
+
this._VerlocityAcc = acc_y;
|
|
3334
|
+
this._VerlocityInit = init_v_y;
|
|
3335
|
+
this._AccAlongX = false;
|
|
3336
|
+
return this;
|
|
3337
|
+
}
|
|
3338
|
+
|
|
3339
|
+
// Start后,当减速到0时结束动画
|
|
3340
|
+
decelerate(acc_x, acc_y, init_v_x, init_v_y) {
|
|
3341
|
+
if (this._Mode !== 1) {
|
|
3342
|
+
console.error("Error: mode error");
|
|
3343
|
+
return;
|
|
3344
|
+
}
|
|
3345
|
+
|
|
3346
|
+
this._VerlocityAcc[0] = acc_x;
|
|
3347
|
+
this._VerlocityAcc[1] = acc_y;
|
|
3348
|
+
this._VerlocityInit[0] = init_v_x;
|
|
3349
|
+
this._VerlocityInit[1] = init_v_y;
|
|
3350
|
+
return this;
|
|
3351
|
+
}
|
|
3352
|
+
|
|
3353
|
+
_ComfirmMode(mode) {
|
|
3354
|
+
if (this._Mode !== mode) {
|
|
3355
|
+
console.error("Error: mode error");
|
|
3356
|
+
return false;
|
|
3357
|
+
}
|
|
3358
|
+
return true;
|
|
3359
|
+
}
|
|
3360
|
+
|
|
3361
|
+
// Override
|
|
3362
|
+
_WrapBuildAnimation(repeat_start_array, current_array, tos_array, act_jump) {
|
|
3363
|
+
if (act_jump) {
|
|
3364
|
+
this._AnimationRef = this._UniformMove(
|
|
3365
|
+
null,
|
|
3366
|
+
current_array,
|
|
3367
|
+
tos_array,
|
|
3368
|
+
act_jump
|
|
3369
|
+
);
|
|
3370
|
+
} else {
|
|
3371
|
+
if (this._Mode === 0) {
|
|
3372
|
+
this._AnimationRef = this._UniformMove(
|
|
3373
|
+
repeat_start_array,
|
|
3374
|
+
current_array,
|
|
3375
|
+
tos_array,
|
|
3376
|
+
false
|
|
3377
|
+
);
|
|
3378
|
+
} else if (this._Mode === 1) {
|
|
3379
|
+
this._AnimationRef = this._AccelerMove(current_array, tos_array);
|
|
3380
|
+
}
|
|
3381
|
+
}
|
|
3382
|
+
return this._AnimationRef;
|
|
3383
|
+
}
|
|
3384
|
+
|
|
3385
|
+
_UniformMove(repeat_start_array, current_array, tos_array, act_jump) {
|
|
3386
|
+
let from_x = 0;
|
|
3387
|
+
let from_y = 0;
|
|
3388
|
+
let start_pos = 0.0;
|
|
3389
|
+
let animate_time = 1;
|
|
3390
|
+
|
|
3391
|
+
const current_x = current_array[0];
|
|
3392
|
+
const current_y = current_array[1];
|
|
3393
|
+
const to_x = tos_array[0];
|
|
3394
|
+
const to_y = tos_array[1];
|
|
3395
|
+
|
|
3396
|
+
if (repeat_start_array !== null) {
|
|
3397
|
+
from_x = repeat_start_array[0];
|
|
3398
|
+
from_y = repeat_start_array[1];
|
|
3399
|
+
const distance = this._Distance(current_x, current_y, to_x, to_y);
|
|
3400
|
+
const distance_total = this._Distance(from_x, from_y, to_x, to_y);
|
|
3401
|
+
start_pos = (distance_total - distance) / distance_total;
|
|
3402
|
+
if (!act_jump) {
|
|
3403
|
+
animate_time = (distance_total * 1000) / this._Speed;
|
|
3404
|
+
}
|
|
3405
|
+
} else {
|
|
3406
|
+
from_x = current_x;
|
|
3407
|
+
from_y = current_y;
|
|
3408
|
+
start_pos = 0.0;
|
|
3409
|
+
if (!act_jump) {
|
|
3410
|
+
animate_time =
|
|
3411
|
+
(this._Distance(current_x, current_y, to_x, to_y) * 1000) /
|
|
3412
|
+
this._Speed;
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
|
|
3416
|
+
if (!act_jump && animate_time === 0) {
|
|
3417
|
+
console.warn("Discard starting request for no distance");
|
|
3418
|
+
// 但动画仍然会执行,为了能正常触发回调
|
|
3419
|
+
}
|
|
3420
|
+
|
|
3421
|
+
let anim = null;
|
|
3422
|
+
if (
|
|
3423
|
+
(from_x === to_x || from_y === to_y) &&
|
|
3424
|
+
!act_jump &&
|
|
3425
|
+
this._AllowFrameStep &&
|
|
3426
|
+
window.JsView
|
|
3427
|
+
) {
|
|
3428
|
+
// 单轴动画时,使用Frame animation来提升平滑性
|
|
3429
|
+
console.log("Using frame translate animation");
|
|
3430
|
+
let position_from = 0;
|
|
3431
|
+
let position_target = 0;
|
|
3432
|
+
let affect_x = true;
|
|
3433
|
+
if (from_x !== to_x) {
|
|
3434
|
+
// X轴方向上的移动
|
|
3435
|
+
position_from = from_x;
|
|
3436
|
+
position_target = to_x;
|
|
3437
|
+
affect_x = true;
|
|
3438
|
+
} else {
|
|
3439
|
+
// Y轴方向上的移动
|
|
3440
|
+
position_from = from_y;
|
|
3441
|
+
position_target = to_y;
|
|
3442
|
+
affect_x = false;
|
|
3443
|
+
}
|
|
3444
|
+
anim = new Forge.TranslateFrameAnimation(
|
|
3445
|
+
position_from,
|
|
3446
|
+
position_target,
|
|
3447
|
+
this._Speed,
|
|
3448
|
+
affect_x
|
|
3449
|
+
);
|
|
3450
|
+
} else {
|
|
3451
|
+
// 创建普通的平移动画
|
|
3452
|
+
anim = new Forge.TranslateAnimation(
|
|
3453
|
+
from_x,
|
|
3454
|
+
to_x,
|
|
3455
|
+
from_y,
|
|
3456
|
+
to_y,
|
|
3457
|
+
animate_time,
|
|
3458
|
+
null
|
|
3459
|
+
);
|
|
3460
|
+
}
|
|
3461
|
+
|
|
3462
|
+
if (start_pos !== 0) {
|
|
3463
|
+
if (start_pos < 0) {
|
|
3464
|
+
console.warn("Warning: start position out of repeating range");
|
|
3465
|
+
} else {
|
|
3466
|
+
anim.SetStartPos(start_pos);
|
|
3467
|
+
}
|
|
3468
|
+
}
|
|
3469
|
+
return anim;
|
|
3470
|
+
}
|
|
3471
|
+
|
|
3472
|
+
_AccelerMove(current_array, tos_array) {
|
|
3473
|
+
const current = this._AccAlongX ? current_array[0] : current_array[1];
|
|
3474
|
+
const init_v = this._VerlocityInit;
|
|
3475
|
+
const acc = this._VerlocityAcc;
|
|
3476
|
+
|
|
3477
|
+
let target;
|
|
3478
|
+
let time;
|
|
3479
|
+
let is_acc_up = true;
|
|
3480
|
+
|
|
3481
|
+
if (acc === 0) {
|
|
3482
|
+
console.error("Error: no found acceleration");
|
|
3483
|
+
return;
|
|
3484
|
+
}
|
|
3485
|
+
|
|
3486
|
+
if (init_v === 0) {
|
|
3487
|
+
// 加速度运动,终点为target x,y
|
|
3488
|
+
target = this._AccAlongX ? tos_array[0] : tos_array[1];
|
|
3489
|
+
|
|
3490
|
+
// d = 0.5 * acc * time^2 ==> time = sqrt(d * 2 / acc)
|
|
3491
|
+
time = Math.floor(
|
|
3492
|
+
Math.sqrt((Math.abs(target - current) * 2) / acc) * 1000
|
|
3493
|
+
);
|
|
3494
|
+
is_acc_up = true;
|
|
3495
|
+
} else {
|
|
3496
|
+
// 减速运动
|
|
3497
|
+
time = Math.floor((Math.abs(init_v) * 1000) / acc);
|
|
3498
|
+
target = current + Math.floor(0.0005 * init_v * time);
|
|
3499
|
+
is_acc_up = false;
|
|
3500
|
+
}
|
|
3501
|
+
|
|
3502
|
+
if (time === 0) {
|
|
3503
|
+
// no move,但动画仍然会执行,为了能正常触发回调
|
|
3504
|
+
console.warn("no moved...");
|
|
3505
|
+
}
|
|
3506
|
+
|
|
3507
|
+
// Update target memo
|
|
3508
|
+
let target_x;
|
|
3509
|
+
let target_y;
|
|
3510
|
+
if (this._AccAlongX) {
|
|
3511
|
+
target_x = target;
|
|
3512
|
+
this._Target[0] = target_x;
|
|
3513
|
+
target_y = this._Target[1];
|
|
3514
|
+
} else {
|
|
3515
|
+
target_x = this._Target[0];
|
|
3516
|
+
target_y = target;
|
|
3517
|
+
this._Target[1] = target_y;
|
|
3518
|
+
}
|
|
3519
|
+
|
|
3520
|
+
return new Forge.TranslateAnimation(
|
|
3521
|
+
current_array[0],
|
|
3522
|
+
target_x,
|
|
3523
|
+
current_array[1],
|
|
3524
|
+
target_y,
|
|
3525
|
+
time,
|
|
3526
|
+
is_acc_up ? Forge.Easing.Circular.In : Forge.Easing.Circular.Out
|
|
3527
|
+
);
|
|
3528
|
+
}
|
|
3529
|
+
|
|
3530
|
+
_Distance(from_x, from_y, to_x, to_y) {
|
|
3531
|
+
const dx = to_x - from_x;
|
|
3532
|
+
const dy = to_y - from_y;
|
|
3533
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
3534
|
+
}
|
|
3535
|
+
|
|
3536
|
+
// Override
|
|
3537
|
+
_WrapCallback(currents, callback) {
|
|
3538
|
+
this._AnimationRef = null; // un-reference
|
|
3539
|
+
if (callback) {
|
|
3540
|
+
callback(currents[0], currents[1]);
|
|
3541
|
+
}
|
|
3542
|
+
}
|
|
3543
|
+
}
|
|
3544
|
+
|
|
3545
|
+
Forge.DragTranslateControl = DragTranslateControl;
|