Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add gifImage in vrender-components #1551

Merged
merged 21 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0e67fd7
fix: fix issue with dirtyBounds incorrectly while set visible
neuqzxy Sep 29, 2024
7b8372c
fix: add clearAABBBounds interface
neuqzxy Sep 29, 2024
9b12fa5
fix: fix issue with dirtyBounds by calc globalAABBBounds
neuqzxy Sep 30, 2024
241e539
fix: fix bug where clearAABBSounds is called when graphic.parent is null
neuqzxy Sep 30, 2024
b293c4c
fix: group bounds valid check ignore visible
neuqzxy Oct 12, 2024
6ae4f59
Merge pull request #1499 from VisActor/develop
neuqzxy Oct 15, 2024
ca44b58
Merge pull request #1480 from VisActor/fix/visible-bounds
neuqzxy Oct 15, 2024
ee55bb1
Merge pull request #1502 from VisActor/develop
neuqzxy Oct 16, 2024
db0155e
build: prelease version 0.21.0-alpha.2
github-actions[bot] Oct 16, 2024
1ca4b70
feat: add gifImage in vrender-components
Rui-Sun Nov 13, 2024
07b1baa
Merge branch 'develop' into feat/gif-image
Rui-Sun Nov 13, 2024
45b6b26
docs: add disableAutoClipedPoptip in text documentation
Rui-Sun Nov 13, 2024
2c6759e
feat: add update in gif-image component
Rui-Sun Nov 13, 2024
3a7e86d
fix: fix gif-canvas clear in GifImage
Rui-Sun Nov 13, 2024
9f1f39c
feat: add animation & name in JSX
Rui-Sun Nov 14, 2024
abb1827
Merge remote-tracking branch 'origin/develop' into feat/gif-image
Rui-Sun Nov 14, 2024
7e6f133
chore: add rush change
Rui-Sun Nov 14, 2024
52a9ece
Merge remote-tracking branch 'origin/pre-release/0.21.0-alpha.2' into…
Rui-Sun Nov 14, 2024
6148c39
feat: move GifImage from vrender-components to vrender-kits
Rui-Sun Nov 18, 2024
dbb1b85
Merge remote-tracking branch 'origin/develop' into feat/gif-image
Rui-Sun Jan 3, 2025
a766717
chore: update merge request
Rui-Sun Jan 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@visactor/vrender-components",
"comment": "feat: add GifImage component",
"type": "none"
}
],
"packageName": "@visactor/vrender-components"
}
12 changes: 12 additions & 0 deletions common/config/rush/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions docs/assets/api/en/common/text.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions docs/assets/api/zh/common/text.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions docs/assets/option/en/common/text.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions docs/assets/option/zh/common/text.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 2 additions & 1 deletion packages/vrender-core/src/interface/graphic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -172,7 +172,7 @@ export class DefaultImageRenderContribution extends DefaultRectRenderContributio
) => boolean
) {
return super.drawShape(
rect,
image,
context,
x,
y,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ export class DefaultCanvasImageRender extends BaseRender<IImage> implements IGra

draw(image: IImage, renderService: IRenderService, drawContext: IDrawContext) {
const { image: url } = image.attribute;

if (!url || !image.resources) {
return;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/vrender-core/src/resource-loader/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion packages/vrender-kits/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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:*",
Expand Down
3 changes: 3 additions & 0 deletions packages/vrender-kits/src/graphic/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Generator } from '@visactor/vrender-core';

export const GIFIMAGE_NUMBER_TYPE = Generator.GenAutoIncrementId();
156 changes: 156 additions & 0 deletions packages/vrender-kits/src/graphic/gif-image.ts
Original file line number Diff line number Diff line change
@@ -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<IGifImageGraphicAttribute>,
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);
}
4 changes: 4 additions & 0 deletions packages/vrender-kits/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
19 changes: 19 additions & 0 deletions packages/vrender-kits/src/interface/gif-image.ts
Original file line number Diff line number Diff line change
@@ -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<IGifImageGraphicAttribute> {
frameImageData?: ImageData;
tempCanvas?: HTMLCanvasElement;
tempCtx?: CanvasRenderingContext2D;
gifCanvas?: HTMLCanvasElement;
gifCtx?: CanvasRenderingContext2D;
loadedFrames?: ParsedFrame[];
frameIndex?: number;
playing?: boolean;
lastTime?: number;
}
18 changes: 17 additions & 1 deletion packages/vrender-kits/src/jsx/jsx-classic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function flatten(list: any, out: any[]): void {
}

export function jsx(type: string | any, config: Record<string, any>, ...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)) {
Expand All @@ -29,6 +29,22 @@ export function jsx(type: string | any, config: Record<string, any>, ...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;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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);
});
Loading
Loading