|
@@ -0,0 +1,231 @@
|
|
|
+import { SPainter, SRect, SSize, SColor, SPoint } from "@saga-web/draw/lib";
|
|
|
+import { SImageShowType, STextOrigin } from "..";
|
|
|
+import { SObjectItem } from "./SObjectItem";
|
|
|
+import { SGraphyItem } from "@saga-web/graphy/lib";
|
|
|
+
|
|
|
+/**
|
|
|
+ * 图片item
|
|
|
+ *
|
|
|
+ * @author 张宇(taohuzy@163.com)
|
|
|
+ */
|
|
|
+export class SImageItem extends SObjectItem {
|
|
|
+ /** 图片dom */
|
|
|
+ img: CanvasImageSource | undefined;
|
|
|
+
|
|
|
+ /** 展示模式 */
|
|
|
+ private _showType: SImageShowType = SImageShowType.Full;
|
|
|
+ get showType(): SImageShowType {
|
|
|
+ return this._showType;
|
|
|
+ }
|
|
|
+ set showType(v: SImageShowType) {
|
|
|
+ this._showType = v;
|
|
|
+ this.computeImgSize();
|
|
|
+ this.update();
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 边框色 */
|
|
|
+ private _strokeColor: SColor = SColor.Transparent;
|
|
|
+ get strokeColor(): SColor {
|
|
|
+ return this._strokeColor;
|
|
|
+ }
|
|
|
+ set strokeColor(v: SColor) {
|
|
|
+ this._strokeColor = v;
|
|
|
+ this.update();
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 边框宽度 */
|
|
|
+ private _lineWidth: number = 1;
|
|
|
+ get lineWidth(): number {
|
|
|
+ return this._lineWidth;
|
|
|
+ }
|
|
|
+ set lineWidth(v: number) {
|
|
|
+ this._lineWidth = v;
|
|
|
+ this.update();
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 原点位置 */
|
|
|
+ private _originPosition: STextOrigin = STextOrigin.LeftTop;
|
|
|
+ get originPosition(): STextOrigin {
|
|
|
+ return this._originPosition;
|
|
|
+ }
|
|
|
+ set originPosition(v: STextOrigin) {
|
|
|
+ this._originPosition = v;
|
|
|
+ this.update();
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 图片加载是否完成 */
|
|
|
+ isLoadOver: boolean = false;
|
|
|
+
|
|
|
+ /** 图片的宽度 */
|
|
|
+ private imgWidth: number = this.width;
|
|
|
+
|
|
|
+ /** 图片的高度 */
|
|
|
+ private imgHeight: number = this.height;
|
|
|
+
|
|
|
+ /** 图片地址 */
|
|
|
+ private _url: string = "";
|
|
|
+ get url(): string {
|
|
|
+ return this._url;
|
|
|
+ }
|
|
|
+ set url(v: string) {
|
|
|
+ this._url = v;
|
|
|
+ this.img = new Image();
|
|
|
+ this.img.onload = (e): void => {
|
|
|
+ // @ts-ignore
|
|
|
+ const imgSrc = e.path[0].src;
|
|
|
+ if (this.isUrlIdentical(imgSrc)) {
|
|
|
+ this.isLoadOver = true;
|
|
|
+ this.computeImgSize();
|
|
|
+ this.$emit("imgLoadOver");
|
|
|
+ this.update();
|
|
|
+ }
|
|
|
+ };
|
|
|
+ this.img.onerror = (e): void => {
|
|
|
+ // @ts-ignore
|
|
|
+ const imgSrc = e.path[0].src;
|
|
|
+ if (this.isUrlIdentical(imgSrc)) {
|
|
|
+ this.isLoadOver = false;
|
|
|
+ this.$emit("imgLoadOver");
|
|
|
+ this.update();
|
|
|
+ console.log("加载图片错误!", e);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ this.img.src = v;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构造函数
|
|
|
+ *
|
|
|
+ * @param parent 指向父Item
|
|
|
+ * @param url 图片地址
|
|
|
+ */
|
|
|
+ constructor(parent: SGraphyItem | null, url?: string) {
|
|
|
+ super(parent);
|
|
|
+ if (url) this.url = url;
|
|
|
+ } // Constructor
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据显示模式计算图片的宽高
|
|
|
+ */
|
|
|
+ computeImgSize(): void {
|
|
|
+ if (this.isLoadOver) {
|
|
|
+ // 要绘制图片的宽度
|
|
|
+ let width = 0;
|
|
|
+ // 要绘制图片的宽度
|
|
|
+ let height = 0;
|
|
|
+ // 图片item的宽高比
|
|
|
+ let itemAspectRatio: number = this.width / this.height;
|
|
|
+ // 原始图片的宽高比
|
|
|
+ let imgAspectRatio: number =
|
|
|
+ // @ts-ignore
|
|
|
+ (this.img.width as number) / (this.img.height as number);
|
|
|
+ // 原始图片的高宽比
|
|
|
+ let imgHwRatio: number =
|
|
|
+ // @ts-ignore
|
|
|
+ (this.img.height as number) / (this.img.width as number);
|
|
|
+ if (this.showType == SImageShowType.Full) {
|
|
|
+ width = this.width;
|
|
|
+ height = this.height;
|
|
|
+ } else if (this.showType == SImageShowType.Equivalency) {
|
|
|
+ if (itemAspectRatio > imgAspectRatio) {
|
|
|
+ height = this.height;
|
|
|
+ width = imgAspectRatio * height;
|
|
|
+ } else if (itemAspectRatio < imgAspectRatio) {
|
|
|
+ width = this.width;
|
|
|
+ height = width * imgHwRatio;
|
|
|
+ } else {
|
|
|
+ width = this.width;
|
|
|
+ height = this.height;
|
|
|
+ }
|
|
|
+ } else if (this.showType == SImageShowType.AutoFit) {
|
|
|
+ // @ts-ignore
|
|
|
+ this.width = this.img.width as number;
|
|
|
+ // @ts-ignore
|
|
|
+ this.height = this.img.height as number;
|
|
|
+ width = this.width;
|
|
|
+ height = this.height;
|
|
|
+ }
|
|
|
+ this.imgWidth = width;
|
|
|
+ this.imgHeight = height;
|
|
|
+ // 设置原点位置(默认左上角)
|
|
|
+ if (this.originPosition == STextOrigin.Centrum) {
|
|
|
+ this.origin = new SPoint(this.width / 2, this.height / 2);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } // Function computeImgSize()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断当前地址和回调地址是否相同
|
|
|
+ * @param imgUrl 图片回调地址
|
|
|
+ *
|
|
|
+ */
|
|
|
+ private isUrlIdentical(imgUrl: string): boolean {
|
|
|
+ if (this.url.indexOf("://") == -1) {
|
|
|
+ const reg = /^\s*data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s]*?)\s*$/i;
|
|
|
+ if (reg.test(this.url)) {
|
|
|
+ // url是base64地址
|
|
|
+ return this.url == imgUrl;
|
|
|
+ } else {
|
|
|
+ // url是相对地址
|
|
|
+ return this.url == this.GetUrlRelativePath(imgUrl);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // url是绝对地址
|
|
|
+ return this.url == imgUrl;
|
|
|
+ }
|
|
|
+ } // Function isUrlIdentical()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 截取绝对路径中的相对路径
|
|
|
+ * @param url 绝对路径
|
|
|
+ *
|
|
|
+ */
|
|
|
+ private GetUrlRelativePath(url: string): string {
|
|
|
+ var arrUrl = url.split("//");
|
|
|
+ var start = arrUrl[1].indexOf("/");
|
|
|
+ var relUrl = arrUrl[1].substring(start);
|
|
|
+ return relUrl;
|
|
|
+ } // Function GetUrlRelativePath()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Item对象边界区域
|
|
|
+ *
|
|
|
+ * @return SRect
|
|
|
+ */
|
|
|
+ boundingRect(): SRect {
|
|
|
+ return new SRect(
|
|
|
+ -this.origin.x,
|
|
|
+ -this.origin.y,
|
|
|
+ this.width,
|
|
|
+ this.height
|
|
|
+ );
|
|
|
+ } // Function boundingRect()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 宽高发发生变化
|
|
|
+ *
|
|
|
+ * @param oldSize 改之前的大小
|
|
|
+ * @param newSize 改之后大小
|
|
|
+ * */
|
|
|
+ protected onResize(oldSize: SSize, newSize: SSize): void {
|
|
|
+ this.computeImgSize();
|
|
|
+ this.update();
|
|
|
+ } // Function onResize()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Item绘制操作
|
|
|
+ *
|
|
|
+ * @param painter 绘画类
|
|
|
+ */
|
|
|
+ onDraw(painter: SPainter): void {
|
|
|
+ painter.translate(-this.origin.x, -this.origin.y);
|
|
|
+ if (this.isLoadOver) {
|
|
|
+ // @ts-ignore
|
|
|
+ painter.drawImage(this.img, 0, 0, this.imgWidth, this.imgHeight);
|
|
|
+ }
|
|
|
+ // painter.pen.lineWidth = this.lineWidth;
|
|
|
+ // painter.pen.color = this.strokeColor;
|
|
|
+ // painter.brush.color = SColor.Transparent;
|
|
|
+ // painter.drawRect(0, 0, this.width, this.height);
|
|
|
+ } // Function onDraw()
|
|
|
+} // Class SImageItem
|