diff --git a/common/changes/@visactor/vrender-components/feat-gif-image_2024-11-14-08-33.json b/common/changes/@visactor/vrender-components/feat-gif-image_2024-11-14-08-33.json new file mode 100644 index 000000000..beccac877 --- /dev/null +++ b/common/changes/@visactor/vrender-components/feat-gif-image_2024-11-14-08-33.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-components", + "comment": "feat: add GifImage component", + "type": "none" + } + ], + "packageName": "@visactor/vrender-components" +} \ No newline at end of file diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index f83c7f160..d2f963e62 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -293,6 +293,7 @@ importers: canvas: 2.11.2 cross-env: ^7.0.3 eslint: ~8.18.0 + gifuct-js: 2.1.2 node-fetch: 2.6.6 react: ^18.0.0 react-dom: ^18.0.0 @@ -303,6 +304,7 @@ importers: '@resvg/resvg-js': 2.4.1 '@visactor/vrender-core': link:../vrender-core '@visactor/vutils': 0.19.3 + gifuct-js: 2.1.2 roughjs: 4.5.2 devDependencies: '@internal/bundler': link:../../tools/bundler @@ -6338,6 +6340,12 @@ packages: assert-plus: 1.0.0 dev: true + /gifuct-js/2.1.2: + resolution: {integrity: sha512-rI2asw77u0mGgwhV3qA+OEgYqaDn5UNqgs+Bx0FGwSpuqfYn+Ir6RQY5ENNQ8SbIiG/m5gVa7CD5RriO4f4Lsg==} + dependencies: + js-binary-schema-parser: 2.0.3 + dev: false + /glob-parent/3.1.0: resolution: {integrity: sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==} dependencies: @@ -8289,6 +8297,10 @@ packages: - ts-node - utf-8-validate + /js-binary-schema-parser/2.0.3: + resolution: {integrity: sha512-xezGJmOb4lk/M1ZZLTR/jaBHQ4gG/lqQnJqdIv4721DMggsa1bDVlHXNeHYogaIEHD9vCRv0fcL4hMA+Coarkg==} + dev: false + /js-string-escape/1.0.1: resolution: {integrity: sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==} engines: {node: '>= 0.8'} diff --git a/docs/assets/api/en/common/text.md b/docs/assets/api/en/common/text.md index d28e2e8df..c21774b92 100644 --- a/docs/assets/api/en/common/text.md +++ b/docs/assets/api/en/common/text.md @@ -36,3 +36,7 @@ Roboto,Helvetica,Arial,sans-serif, apple color emoji,segoe ui emoji,segoe ui sym #${prefix} lineThrough(number) = 0 中划线线粗 + +#${prefix} disableAutoClipedPoptip(boolean) = false + +禁用省略hover展示poptip \ No newline at end of file diff --git a/docs/assets/api/zh/common/text.md b/docs/assets/api/zh/common/text.md index d28e2e8df..c21774b92 100644 --- a/docs/assets/api/zh/common/text.md +++ b/docs/assets/api/zh/common/text.md @@ -36,3 +36,7 @@ Roboto,Helvetica,Arial,sans-serif, apple color emoji,segoe ui emoji,segoe ui sym #${prefix} lineThrough(number) = 0 中划线线粗 + +#${prefix} disableAutoClipedPoptip(boolean) = false + +禁用省略hover展示poptip \ No newline at end of file diff --git a/docs/assets/option/en/common/text.md b/docs/assets/option/en/common/text.md index d28e2e8df..c21774b92 100644 --- a/docs/assets/option/en/common/text.md +++ b/docs/assets/option/en/common/text.md @@ -36,3 +36,7 @@ Roboto,Helvetica,Arial,sans-serif, apple color emoji,segoe ui emoji,segoe ui sym #${prefix} lineThrough(number) = 0 中划线线粗 + +#${prefix} disableAutoClipedPoptip(boolean) = false + +禁用省略hover展示poptip \ No newline at end of file diff --git a/docs/assets/option/zh/common/text.md b/docs/assets/option/zh/common/text.md index d28e2e8df..c21774b92 100644 --- a/docs/assets/option/zh/common/text.md +++ b/docs/assets/option/zh/common/text.md @@ -36,3 +36,7 @@ Roboto,Helvetica,Arial,sans-serif, apple color emoji,segoe ui emoji,segoe ui sym #${prefix} lineThrough(number) = 0 中划线线粗 + +#${prefix} disableAutoClipedPoptip(boolean) = false + +禁用省略hover展示poptip \ No newline at end of file diff --git a/packages/vrender-core/src/interface/graphic.ts b/packages/vrender-core/src/interface/graphic.ts index 6781ff69a..ab233abe3 100644 --- a/packages/vrender-core/src/interface/graphic.ts +++ b/packages/vrender-core/src/interface/graphic.ts @@ -38,7 +38,8 @@ export type GraphicType = | 'shadowroot' | 'polygon' | 'pyramid3d' - | 'glyph'; + | 'glyph' + | string; // Cursor style // See: https://developer.mozilla.org/en-US/docs/Web/CSS/cursor diff --git a/packages/vrender-core/src/render/contributions/render/contributions/image-contribution-render.ts b/packages/vrender-core/src/render/contributions/render/contributions/image-contribution-render.ts index 37a95be2d..dd3309aba 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/image-contribution-render.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/image-contribution-render.ts @@ -150,7 +150,7 @@ export class DefaultImageRenderContribution extends DefaultRectRenderContributio useStyle: boolean = true; order: number = 0; drawShape( - rect: any, + image: any, context: IContext2d, x: number, y: number, @@ -172,7 +172,7 @@ export class DefaultImageRenderContribution extends DefaultRectRenderContributio ) => boolean ) { return super.drawShape( - rect, + image, context, x, y, diff --git a/packages/vrender-core/src/render/contributions/render/image-render.ts b/packages/vrender-core/src/render/contributions/render/image-render.ts index 9ba01bdce..50c14622d 100644 --- a/packages/vrender-core/src/render/contributions/render/image-render.ts +++ b/packages/vrender-core/src/render/contributions/render/image-render.ts @@ -169,6 +169,7 @@ export class DefaultCanvasImageRender extends BaseRender implements IGra draw(image: IImage, renderService: IRenderService, drawContext: IDrawContext) { const { image: url } = image.attribute; + if (!url || !image.resources) { return; } diff --git a/packages/vrender-core/src/resource-loader/loader.ts b/packages/vrender-core/src/resource-loader/loader.ts index 55c779829..f40326744 100644 --- a/packages/vrender-core/src/resource-loader/loader.ts +++ b/packages/vrender-core/src/resource-loader/loader.ts @@ -108,9 +108,9 @@ export class ResourceLoader { let data = ResourceLoader.cache.get(url); if (data) { // 存在缓存 - if (data.loadState === 'init' || data.loadState === 'fail') { + if (data.loadState === 'fail') { return Promise.reject(); - } else if (data.loadState === 'loading') { + } else if (data.loadState === 'init' || data.loadState === 'loading') { return data.dataPromise.then(data => data.data); } return Promise.resolve(data.data); diff --git a/packages/vrender-kits/package.json b/packages/vrender-kits/package.json index a378737bc..51c1730b2 100644 --- a/packages/vrender-kits/package.json +++ b/packages/vrender-kits/package.json @@ -23,7 +23,8 @@ "@visactor/vutils": "~0.19.3", "@visactor/vrender-core": "workspace:0.21.7", "@resvg/resvg-js": "2.4.1", - "roughjs": "4.5.2" + "roughjs": "4.5.2", + "gifuct-js": "2.1.2" }, "devDependencies": { "@internal/bundler": "workspace:*", diff --git a/packages/vrender-kits/src/graphic/constants.ts b/packages/vrender-kits/src/graphic/constants.ts new file mode 100644 index 000000000..c234ac0eb --- /dev/null +++ b/packages/vrender-kits/src/graphic/constants.ts @@ -0,0 +1,3 @@ +import { Generator } from '@visactor/vrender-core'; + +export const GIFIMAGE_NUMBER_TYPE = Generator.GenAutoIncrementId(); diff --git a/packages/vrender-kits/src/graphic/gif-image.ts b/packages/vrender-kits/src/graphic/gif-image.ts new file mode 100644 index 000000000..2e930233d --- /dev/null +++ b/packages/vrender-kits/src/graphic/gif-image.ts @@ -0,0 +1,156 @@ +import type { IImageGraphicAttribute, ISetAttributeContext } from '@visactor/vrender-core'; +import { application, Image, ResourceLoader } from '@visactor/vrender-core'; +import type { ITimeline } from '@visactor/vrender-core'; +import { isString } from '@visactor/vutils'; +import type { ParsedFrame } from 'gifuct-js'; +import { decompressFrames, parseGIF } from 'gifuct-js'; +import type { IGifImage, IGifImageGraphicAttribute } from '../interface/gif-image'; +import { GIFIMAGE_NUMBER_TYPE } from './constants'; + +export class GifImage extends Image implements IGifImage { + type: any = 'gif-image'; + declare attribute: IGifImageGraphicAttribute; + + frameImageData?: ImageData; + tempCanvas?: HTMLCanvasElement; + tempCtx?: CanvasRenderingContext2D; + gifCanvas?: HTMLCanvasElement; + gifCtx?: CanvasRenderingContext2D; + loadedFrames?: ParsedFrame[]; + frameIndex?: number; + playing?: boolean; + lastTime?: number; + + constructor(params: IGifImageGraphicAttribute) { + super(params); + this.numberType = GIFIMAGE_NUMBER_TYPE; + this.loadGif(); + } + + loadGif() { + if (isString(this.attribute.gifImage)) { + ResourceLoader.GetFile(this.attribute.gifImage, 'arrayBuffer') + .then((res: ArrayBuffer) => { + const gif = parseGIF(res); + const frames = decompressFrames(gif, true); + this.renderGIF(frames); + }) + .catch(e => { + console.error('Gif load error: ', e); + }); + } else if (this.attribute.gifImage instanceof ArrayBuffer) { + const gif = parseGIF(this.attribute.gifImage); + const frames = decompressFrames(gif, true); + this.renderGIF(frames); + } + } + + renderGIF(frames: ParsedFrame[]) { + this.loadedFrames = frames; + this.frameIndex = 0; + + if (!this.tempCanvas) { + this.tempCanvas = application.global.createCanvas({}); + this.tempCtx = this.tempCanvas.getContext('2d'); + } + + if (!this.gifCanvas) { + this.gifCanvas = application.global.createCanvas({}); + this.gifCtx = this.gifCanvas.getContext('2d'); + } + + this.gifCanvas.width = frames[0].dims.width; + this.gifCanvas.height = frames[0].dims.height; + + this.playing = true; + this.lastTime = new Date().getTime(); + const animation = this.animate(); + if (this.attribute.timeline) { + animation.setTimeline(this.attribute.timeline); + } + animation.to({}, 1000, 'linear').loop(Infinity); + } + + renderFrame(context: CanvasRenderingContext2D, x: number, y: number) { + // get the frame + const frame = this.loadedFrames[this.frameIndex || 0]; + + if (frame.disposalType === 2) { + this.gifCtx.clearRect(0, 0, this.gifCanvas.width, this.gifCanvas.height); + } + + // draw image into gifCanvas + this.drawPatch(frame); + + // draw gifCanvas into stage + this.manipulate(context, x, y); + + // update the frame index + const diff = new Date().getTime() - this.lastTime; + if (frame.delay < diff) { + this.frameIndex++; + this.lastTime = new Date().getTime(); + } + if (this.frameIndex >= this.loadedFrames.length) { + this.frameIndex = 0; + } + } + + drawPatch(frame: ParsedFrame) { + const dims = frame.dims; + + if ( + !this.frameImageData || + dims.width !== this.frameImageData.width || + dims.height !== this.frameImageData.height + ) { + this.tempCanvas.width = dims.width; + this.tempCanvas.height = dims.height; + this.frameImageData = this.tempCtx.createImageData(dims.width, dims.height); + } + + // set the patch data as an override + this.frameImageData.data.set(frame.patch); + + // draw the patch back over the canvas + this.tempCtx.putImageData(this.frameImageData, 0, 0); + + this.gifCtx.drawImage(this.tempCanvas, dims.left, dims.top); + } + + manipulate(context: CanvasRenderingContext2D, x: number, y: number) { + context.drawImage( + this.gifCanvas, + 0, + 0, + this.gifCanvas.width, + this.gifCanvas.height, + x, + y, + this.attribute.width, + this.attribute.height + ); + } + + setAttribute(key: string, value: any, forceUpdateTag?: boolean, context?: ISetAttributeContext): void { + super.setAttribute(key, value, forceUpdateTag, context); + if (key === 'gifImage') { + this.loadGif(); + } + } + + setAttributes( + params: Partial, + forceUpdateTag?: boolean, + context?: ISetAttributeContext + ): void { + super.setAttributes(params, forceUpdateTag, context); + if (params.gifImage) { + this.loadGif(); + } + } +} + +export function createGifImage(attributes: IGifImageGraphicAttribute): IGifImage { + return new GifImage(attributes); +} diff --git a/packages/vrender-kits/src/index.ts b/packages/vrender-kits/src/index.ts index 9a24112ec..6b68fef67 100644 --- a/packages/vrender-kits/src/index.ts +++ b/packages/vrender-kits/src/index.ts @@ -51,6 +51,10 @@ export * from './picker/contributions/canvas-picker/arc3d-module'; export * from './picker/contributions/canvas-picker/pyramid3d-module'; +export * from './graphic/gif-image'; +export * from './picker/contributions/canvas-picker/gif-image-module'; +export * from './render/contributions/canvas/gif-image-module'; + export * from './register/register-arc'; export * from './register/register-arc3d'; export * from './register/register-area'; diff --git a/packages/vrender-kits/src/interface/gif-image.ts b/packages/vrender-kits/src/interface/gif-image.ts new file mode 100644 index 000000000..891c3dbde --- /dev/null +++ b/packages/vrender-kits/src/interface/gif-image.ts @@ -0,0 +1,19 @@ +import type { IGraphic, IImageGraphicAttribute, ITimeline } from '@visactor/vrender-core'; +import type { ParsedFrame } from 'gifuct-js'; + +export interface IGifImageGraphicAttribute extends IImageGraphicAttribute { + timeline?: ITimeline; + gifImage?: string | ArrayBuffer; +} + +export interface IGifImage extends IGraphic { + frameImageData?: ImageData; + tempCanvas?: HTMLCanvasElement; + tempCtx?: CanvasRenderingContext2D; + gifCanvas?: HTMLCanvasElement; + gifCtx?: CanvasRenderingContext2D; + loadedFrames?: ParsedFrame[]; + frameIndex?: number; + playing?: boolean; + lastTime?: number; +} diff --git a/packages/vrender-kits/src/jsx/jsx-classic.ts b/packages/vrender-kits/src/jsx/jsx-classic.ts index ad56ff823..f6ea0fdb2 100644 --- a/packages/vrender-kits/src/jsx/jsx-classic.ts +++ b/packages/vrender-kits/src/jsx/jsx-classic.ts @@ -10,7 +10,7 @@ function flatten(list: any, out: any[]): void { } export function jsx(type: string | any, config: Record, ...children: any) { - const { key, name, id, attribute, stateProxy, ...props } = config || {}; + const { key, name, id, attribute, stateProxy, animation, timeline, ...props } = config || {}; let c = type; if (isString(type)) { @@ -29,6 +29,22 @@ export function jsx(type: string | any, config: Record, ...children g.stateProxy = stateProxy; } + if (name) { + g.name = name; + } + + if (isArray(animation)) { + // animation={[ + // ['to', { angle: 2 * Math.PI }, 1000, 'linear'], + // ['loop', Infinity] + // ]} + const animate = g.animate(); + timeline && animate.setTimeline(timeline); + animation.forEach((item: any[]) => { + animate[item[0]](...item.slice(1)); + }); + } + return g; } diff --git a/packages/vrender-kits/src/picker/contributions/canvas-picker/gif-image-module.ts b/packages/vrender-kits/src/picker/contributions/canvas-picker/gif-image-module.ts new file mode 100644 index 000000000..755c5eec0 --- /dev/null +++ b/packages/vrender-kits/src/picker/contributions/canvas-picker/gif-image-module.ts @@ -0,0 +1,14 @@ +import { ContainerModule } from '@visactor/vrender-core'; +import { CanvasGifImagePicker, CanvasPickerContribution } from '../constants'; +import { DefaultCanvasGifImagePicker } from './gif-image-picker'; + +let loadGifImagePick = false; +export const gifImageCanvasPickModule = new ContainerModule((bind, unbind, isBound, rebind) => { + if (loadGifImagePick) { + return; + } + loadGifImagePick = true; + // gifGifImage picker + bind(CanvasGifImagePicker).to(DefaultCanvasGifImagePicker).inSingletonScope(); + bind(CanvasPickerContribution).toService(CanvasGifImagePicker); +}); diff --git a/packages/vrender-kits/src/picker/contributions/canvas-picker/gif-image-picker.ts b/packages/vrender-kits/src/picker/contributions/canvas-picker/gif-image-picker.ts new file mode 100644 index 000000000..4a7634db5 --- /dev/null +++ b/packages/vrender-kits/src/picker/contributions/canvas-picker/gif-image-picker.ts @@ -0,0 +1,31 @@ +import type { IPoint } from '@visactor/vutils'; +import { injectable } from '@visactor/vrender-core'; +import type { IGraphicPicker, IPickParams } from '@visactor/vrender-core'; +import type { IGifImage } from '../../../interface/gif-image'; +import { GIFIMAGE_NUMBER_TYPE } from '../../../graphic/constants'; + +@injectable() +export class DefaultCanvasGifImagePicker implements IGraphicPicker { + type: string = 'gif-image'; + numberType: number = GIFIMAGE_NUMBER_TYPE; + + contains(gifImage: IGifImage, point: IPoint, params?: IPickParams): boolean { + // const { gifImageAttribute } = graphicService.themeService.getCurrentTheme(); + // const { + // x = gifImageAttribute.x, + // y = gifImageAttribute.y, + // } = gifImage.attribute; + + const { pickContext } = params ?? {}; + if (!pickContext) { + return false; + } + + if (!gifImage.AABBBounds.containsPoint(point)) { + return false; + } + + // TODO: 详细形状判断 + return true; + } +} diff --git a/packages/vrender-kits/src/picker/contributions/constants.ts b/packages/vrender-kits/src/picker/contributions/constants.ts index 4ce53d35b..f2c09d01f 100644 --- a/packages/vrender-kits/src/picker/contributions/constants.ts +++ b/packages/vrender-kits/src/picker/contributions/constants.ts @@ -19,6 +19,7 @@ export const CanvasArc3dPicker = Symbol.for('CanvasArc3dPicker'); export const CanvasAreaPicker = Symbol.for('CanvasAreaPicker'); export const CanvasCirclePicker = Symbol.for('CanvasCirclePicker'); export const CanvasImagePicker = Symbol.for('CanvasImagePicker'); +export const CanvasGifImagePicker = Symbol.for('CanvasGifImagePicker'); export const CanvasLinePicker = Symbol.for('CanvasLinePicker'); export const CanvasPathPicker = Symbol.for('CanvasPathPicker'); export const CanvasRectPicker = Symbol.for('CanvasRectPicker'); diff --git a/packages/vrender-kits/src/render/contributions/canvas/gif-image-module.ts b/packages/vrender-kits/src/render/contributions/canvas/gif-image-module.ts new file mode 100644 index 000000000..be568f750 --- /dev/null +++ b/packages/vrender-kits/src/render/contributions/canvas/gif-image-module.ts @@ -0,0 +1,13 @@ +import { ContainerModule, GraphicRender } from '@visactor/vrender-core'; +import { DefaultCanvasGifImageRender } from './gif-image-render'; + +let loadGifImageModule = false; +export const gifImageModule = new ContainerModule(bind => { + if (loadGifImageModule) { + return; + } + loadGifImageModule = true; + // gifImage渲染器 + bind(DefaultCanvasGifImageRender).toSelf().inSingletonScope(); + bind(GraphicRender).toService(DefaultCanvasGifImageRender); +}); diff --git a/packages/vrender-kits/src/render/contributions/canvas/gif-image-render.ts b/packages/vrender-kits/src/render/contributions/canvas/gif-image-render.ts new file mode 100644 index 000000000..d65f4976f --- /dev/null +++ b/packages/vrender-kits/src/render/contributions/canvas/gif-image-render.ts @@ -0,0 +1,87 @@ +import type { + IContext2d, + IContributionProvider, + IDrawContext, + IGraphicAttribute, + IGraphicRender, + IImageRenderContribution, + IMarkAttribute, + IRenderService, + IThemeAttribute +} from '@visactor/vrender-core'; +import { + BaseRenderContributionTime, + ContributionProvider, + DefaultCanvasImageRender, + DefaultRectRenderContribution, + getTheme, + ImageRenderContribution, + inject, + injectable, + named +} from '@visactor/vrender-core'; +import { GIFIMAGE_NUMBER_TYPE } from '../../../graphic/constants'; +import type { IGifImage } from '../../../interface/gif-image'; + +@injectable() +export class DefaultCanvasGifImageRender extends DefaultCanvasImageRender implements IGraphicRender { + type: 'image'; + numberType: number = GIFIMAGE_NUMBER_TYPE; + + constructor( + @inject(ContributionProvider) + @named(ImageRenderContribution) + protected readonly imageRenderContribitions: IContributionProvider + ) { + super(imageRenderContribitions); + this._renderContribitions = undefined; + this.builtinContributions = [defaultGifImageRenderContribution]; + this.init(imageRenderContribitions); + } + + draw(image: IGifImage, renderService: IRenderService, drawContext: IDrawContext) { + const { context } = renderService.drawParams; + if (!context) { + return; + } + const imageAttribute = getTheme(image).image; + this._draw(image, imageAttribute, false, drawContext); + } +} + +export class DefaultGifImageRenderContribution + extends DefaultRectRenderContribution + implements IImageRenderContribution +{ + time: BaseRenderContributionTime = BaseRenderContributionTime.afterFillStroke; + useStyle: boolean = true; + order: number = 0; + drawShape( + image: any, + context: IContext2d, + x: number, + y: number, + doFill: boolean, + doStroke: boolean, + fVisible: boolean, + sVisible: boolean, + rectAttribute: any, + drawContext: IDrawContext, + fillCb?: ( + ctx: IContext2d, + markAttribute: Partial, + themeAttribute: IThemeAttribute + ) => boolean, + strokeCb?: ( + ctx: IContext2d, + markAttribute: Partial, + themeAttribute: IThemeAttribute + ) => boolean + ) { + if (image.renderFrame && image.playing) { + image.renderFrame(context, x, y); + } + } +} + +export const defaultGifImageRenderContribution = new DefaultGifImageRenderContribution(); diff --git a/packages/vrender/__tests__/browser/sources/loading-1.gif b/packages/vrender/__tests__/browser/sources/loading-1.gif new file mode 100644 index 000000000..20ac5cb44 Binary files /dev/null and b/packages/vrender/__tests__/browser/sources/loading-1.gif differ diff --git a/packages/vrender/__tests__/browser/sources/loading.gif b/packages/vrender/__tests__/browser/sources/loading.gif new file mode 100644 index 000000000..0c81bcaf8 Binary files /dev/null and b/packages/vrender/__tests__/browser/sources/loading.gif differ diff --git a/packages/vrender/__tests__/browser/src/pages/gif-image.ts b/packages/vrender/__tests__/browser/src/pages/gif-image.ts new file mode 100644 index 000000000..8900d5098 --- /dev/null +++ b/packages/vrender/__tests__/browser/src/pages/gif-image.ts @@ -0,0 +1,64 @@ +import { createStage, container } from '@visactor/vrender-core'; +import { GifImage, IGifImageGraphicAttribute, gifImageModule, gifImageCanvasPickModule } from '@visactor/vrender-kits'; +import { addShapesToStage, colorPools } from '../utils'; + +container.load(gifImageModule); +container.load(gifImageCanvasPickModule); + +export const page = () => { + const shapes = []; + shapes.push( + new GifImage({ + x: 100, + y: 100, + width: 50, + height: 50, + gifImage: './sources/loading.gif' + } as IGifImageGraphicAttribute) + ); + + shapes.push( + new GifImage({ + x: 200, + y: 100, + width: 50, + height: 50, + gifImage: './sources/loading.gif' + } as IGifImageGraphicAttribute) + ); + + shapes.push( + new GifImage({ + x: 100, + y: 200, + width: 50, + height: 50, + gifImage: './sources/loading-1.gif' + } as IGifImageGraphicAttribute) + ); + + shapes.push( + new GifImage({ + x: 200, + y: 200, + width: 50, + height: 50, + gifImage: './sources/loading-1.gif' + } as IGifImageGraphicAttribute) + ); + + const stage = createStage({ + canvas: 'main', + width: 1200, + height: 600, + viewWidth: 1200, + viewHeight: 600 + }); + + addShapesToStage(stage, shapes as any, true); + stage.render(); + + stage.addEventListener('click', e => { + console.log('target', e.target); + }); +}; diff --git a/packages/vrender/__tests__/browser/src/pages/index.ts b/packages/vrender/__tests__/browser/src/pages/index.ts index 8eff30472..2fed4b3de 100644 --- a/packages/vrender/__tests__/browser/src/pages/index.ts +++ b/packages/vrender/__tests__/browser/src/pages/index.ts @@ -190,6 +190,10 @@ export const pages = [ { name: 'react', path: 'react' + }, + { + name: 'gif-image', + path: 'gif-image' } ] },