mh-two-thousand-and-two
2024-03-25 b8c93990f3fa5e50a8aca16bdc9c2758168aa0fd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import Displayable, { DisplayableProps,
    CommonStyleProps,
    DEFAULT_COMMON_STYLE,
    DisplayableStatePropNames,
    DEFAULT_COMMON_ANIMATION_PROPS
} from './Displayable';
import BoundingRect from '../core/BoundingRect';
import { ImageLike, MapToType } from '../core/types';
import { defaults, createObject } from '../core/util';
import { ElementCommonState } from '../Element';
 
export interface ImageStyleProps extends CommonStyleProps {
    image?: string | ImageLike
    x?: number
    y?: number
    width?: number
    height?: number
    sx?: number
    sy?: number
    sWidth?: number
    sHeight?: number
}
 
export const DEFAULT_IMAGE_STYLE: CommonStyleProps = defaults({
    x: 0,
    y: 0
}, DEFAULT_COMMON_STYLE);
 
export const DEFAULT_IMAGE_ANIMATION_PROPS: MapToType<ImageProps, boolean> = {
    style: defaults<MapToType<ImageStyleProps, boolean>, MapToType<ImageStyleProps, boolean>>({
        x: true,
        y: true,
        width: true,
        height: true,
        sx: true,
        sy: true,
        sWidth: true,
        sHeight: true
    }, DEFAULT_COMMON_ANIMATION_PROPS.style)
 };
 
export interface ImageProps extends DisplayableProps {
    style?: ImageStyleProps
 
    onload?: (image: ImageLike) => void
}
 
export type ImageState = Pick<ImageProps, DisplayableStatePropNames> & ElementCommonState
 
function isImageLike(source: unknown): source is HTMLImageElement {
    return !!(source
        && typeof source !== 'string'
        // Image source is an image, canvas, video.
        && (source as HTMLImageElement).width && (source as HTMLImageElement).height);
}
 
class ZRImage extends Displayable<ImageProps> {
 
    style: ImageStyleProps
 
    // FOR CANVAS RENDERER
    __image: ImageLike
    // FOR SVG RENDERER
    __imageSrc: string
 
    onload: (image: ImageLike) => void
 
    /**
     * Create an image style object with default values in it's prototype.
     * @override
     */
    createStyle(obj?: ImageStyleProps) {
        return createObject(DEFAULT_IMAGE_STYLE, obj);
    }
 
    private _getSize(dim: 'width' | 'height') {
        const style = this.style;
 
        let size = style[dim];
        if (size != null) {
            return size;
        }
 
        const imageSource = isImageLike(style.image)
            ? style.image : this.__image;
 
        if (!imageSource) {
            return 0;
        }
 
        const otherDim = dim === 'width' ? 'height' : 'width';
        let otherDimSize = style[otherDim];
        if (otherDimSize == null) {
            return imageSource[dim];
        }
        else {
            return imageSource[dim] / imageSource[otherDim] * otherDimSize;
        }
    }
 
    getWidth(): number {
        return this._getSize('width');
    }
 
    getHeight(): number {
        return this._getSize('height');
    }
 
    getAnimationStyleProps() {
        return DEFAULT_IMAGE_ANIMATION_PROPS;
    }
 
    getBoundingRect(): BoundingRect {
        const style = this.style;
        if (!this._rect) {
            this._rect = new BoundingRect(
                style.x || 0, style.y || 0, this.getWidth(), this.getHeight()
            );
        }
        return this._rect;
    }
}
 
ZRImage.prototype.type = 'image';
 
export default ZRImage;