Pārlūkot izejas kodu

引擎渐变色及图形融合支持

haojianlong 5 gadi atpakaļ
vecāks
revīzija
5bc17bd5db

+ 1 - 1
saga-web-draw/.eslintrc.js

@@ -20,7 +20,7 @@ module.exports = {
     },
     rules: {
         // 缩进
-        'indent': ['error', 4],                         // 缩进控制4空格
+        'indent': ['error', 4, { SwitchCase: 1 }],      // 缩进控制4空格
         'max-len': ['error', 120],                      // 每行字符不超过120
         'no-mixed-spaces-and-tabs': 'error',            // 禁止使用空格和tab混合缩进
         // 语句

+ 1 - 1
saga-web-draw/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@saga-web/draw",
-    "version": "2.1.75",
+    "version": "2.1.76",
     "description": "上格云绘制引擎。",
     "main": "lib/index.js",
     "types": "lib/index.d.js",

+ 1 - 1
saga-web-draw/src/SGradient.ts

@@ -17,5 +17,5 @@ export abstract class SGradient {
      */
     addColorStop(pos: number, color: SColor): void {
         this.stopList.push(new SGradientStop(pos, color));
-    } // Functin addColorStop()
+    } // Function addColorStop()
 } // Class SGradientStop

+ 10 - 0
saga-web-draw/src/SPainter.ts

@@ -12,6 +12,7 @@ import {
     SRect,
     SSize
 } from "./";
+import {SCompositeType} from "./enums/SCompositeType";
 
 /**
  * Painter
@@ -48,6 +49,14 @@ export class SPainter extends SObject {
         this.engine.state.font = value;
     } // Set font
 
+    /** 融合属性 */
+    get composite(): number {
+        return this.engine.state._composite;
+    } // Get composite
+    set composite(value: number) {
+        this.engine.state._composite = value;
+    } // Set composite
+
     /** 变换矩阵 */
     get worldTransform(): DOMMatrix {
         return this.engine.state.matrix;
@@ -70,6 +79,7 @@ export class SPainter extends SObject {
         this.pen = new SPen();
         this.brush = new SBrush();
         this.font = new SFont();
+        this.composite = SCompositeType.SourceOver;
     } // Constructor()
 
     /**

+ 98 - 5
saga-web-draw/src/engines/SCanvasPaintEngine.ts

@@ -1,15 +1,20 @@
 import { SPaintEngine } from "./SPaintEngine";
 import {
+    SBrushType,
+    SGradientStop,
     SLine,
+    SLinearGradient,
     SLineCapStyle,
     SPaintEngineType,
     SPoint,
+    SRadialGradient,
     SRect,
     STextAlign,
     STextBaseLine,
     STextDirection
 } from "..";
 import { SPath2D } from "../SPath2D";
+import { SCompositeType } from "../enums/SCompositeType";
 
 /**
  * Canvas绘制引擎基类
@@ -78,6 +83,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
         this.setMatrix();
         this.setPen();
         this.setBrush();
+        this.setComposite();
         this._canvas.fillRect(rect.x, rect.y, rect.width, rect.height);
         this._canvas.strokeRect(rect.x, rect.y, rect.width, rect.height);
     } // Function drawRect()
@@ -93,6 +99,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
         this.setMatrix();
         this.setPen();
         this.setBrush();
+        this.setComposite();
         this._canvas.beginPath();
         this._canvas.arc(cx, cy, r, 0, 2 * Math.PI, true);
         this._canvas.fill();
@@ -111,6 +118,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
         this.setMatrix();
         this.setPen();
         this.setBrush();
+        this.setComposite();
         this._canvas.beginPath();
         this._canvas.ellipse(cx, cy, rx, ry, 0.5, 0, 2 * Math.PI, true);
     } // Function drawEllipse()
@@ -136,6 +144,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
         this.setMatrix();
         this.setPen();
         this.setBrush();
+        this.setComposite();
         let p = SPath2D.arc(x, y, width, height, startAngle, endAngle);
         let path = new Path2D(
             SPath2D.arc(x, y, width, height, startAngle, endAngle)
@@ -164,6 +173,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
         this.setMatrix();
         this.setPen();
         this.setBrush();
+        this.setComposite();
         let path = new Path2D(
             SPath2D.chord(x, y, width, height, startAngle, endAngle)
         );
@@ -193,6 +203,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
         this.setMatrix();
         this.setPen();
         this.setBrush();
+        this.setComposite();
         let path = new Path2D(
             SPath2D.pie(x, y, width, height, startAngle, endAngle)
         );
@@ -209,6 +220,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
         this.setMatrix();
         this.setPen();
         this.setBrush();
+        this.setComposite();
         this._canvas.beginPath();
         this._canvas.moveTo(line.x1, line.y1);
         this._canvas.lineTo(line.x2, line.y2);
@@ -229,6 +241,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
         this.setMatrix();
         this.setPen();
         this.setBrush();
+        this.setComposite();
 
         this._canvas.beginPath();
         this._canvas.moveTo(points[0].x, points[0].y);
@@ -253,6 +266,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
         this.setMatrix();
         this.setPen();
         this.setBrush();
+        this.setComposite();
 
         this._canvas.beginPath();
         this._canvas.moveTo(points[0].x, points[0].y);
@@ -274,6 +288,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
         this.setMatrix();
         this.setPen();
         this.setBrush();
+        this.setComposite();
 
         this._canvas.fill(path._path);
         this._canvas.stroke(path._path);
@@ -292,6 +307,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
         this.setPen();
         this.setBrush();
         this.setFont();
+        this.setComposite();
 
         if (maxWidth == undefined) {
             this._canvas.fillText(text, x, y);
@@ -397,13 +413,90 @@ export class SCanvasPaintEngine extends SPaintEngine {
      */
     private setBrush(): void {
         // this._canvas.fillStyle = this.state.brush.color.value;
-        this._canvas.fillStyle = `rgba(${this.state.brush.color.red}, ${
-            this.state.brush.color.green
-        }, ${this.state.brush.color.blue}, ${this.state.brush.color.alpha /
-            255.0})`;
+        if (this.state.brush.type == SBrushType.Color) {
+            this._canvas.fillStyle = `rgba(${this.state.brush.color.red}, ${
+                this.state.brush.color.green
+            }, ${this.state.brush.color.blue}, ${this.state.brush.color.alpha /
+                255.0})`;
+        } else if (this.state.brush.type == SBrushType.Gradient) {
+            let gradient = this.state.brush.gradient,
+                drawGradient: CanvasGradient;
+            if (gradient instanceof SLinearGradient) {
+                drawGradient = this._canvas.createLinearGradient(
+                    gradient.x1,
+                    gradient.y1,
+                    gradient.x2,
+                    gradient.y2
+                );
+            } else if (gradient instanceof SRadialGradient) {
+                drawGradient = this._canvas.createRadialGradient(
+                    gradient.x1,
+                    gradient.y1,
+                    gradient.r1,
+                    gradient.x2,
+                    gradient.y2,
+                    gradient.r2
+                );
+            }
+            // @ts-ignore
+            if (gradient && drawGradient) {
+                gradient.stopList.forEach((t: SGradientStop): void => {
+                    drawGradient.addColorStop(
+                        t.pos,
+                        `rgba(${t.color.red},${t.color.green},${t.color.blue},${t.color.alpha})`
+                    );
+                });
+                this._canvas.fillStyle = drawGradient;
+            }
+        }
     } // Function setBrush()
 
     /**
+     * 设置融合
+     */
+    private setComposite(): void {
+        const type = this.state._composite;
+        switch (type) {
+            case SCompositeType.SourceOver:
+                this._canvas.globalCompositeOperation = "source-over";
+                return;
+            case SCompositeType.Copy:
+                this._canvas.globalCompositeOperation = "copy";
+                return;
+            case SCompositeType.DestinationAtop:
+                this._canvas.globalCompositeOperation = "destination-atop";
+                return;
+            case SCompositeType.DestinationIn:
+                this._canvas.globalCompositeOperation = "destination-in";
+                return;
+            case SCompositeType.DestinationOut:
+                this._canvas.globalCompositeOperation = "destination-out";
+                return;
+            case SCompositeType.DestinationOver:
+                this._canvas.globalCompositeOperation = "destination-over";
+                return;
+            case SCompositeType.Lighter:
+                this._canvas.globalCompositeOperation = "lighter";
+                return;
+            case SCompositeType.SourceAtop:
+                this._canvas.globalCompositeOperation = "source-atop";
+                return;
+            case SCompositeType.SourceIn:
+                this._canvas.globalCompositeOperation = "source-in";
+                return;
+            case SCompositeType.SourceOut:
+                this._canvas.globalCompositeOperation = "source-out";
+                return;
+            case SCompositeType.Xor:
+                this._canvas.globalCompositeOperation = "xor";
+                return;
+            default:
+                this._canvas.globalCompositeOperation = "source-over";
+                return;
+        }
+    } // Function setComposite()
+
+    /**
      * 设置字体
      */
     private setFont(): void {
@@ -416,7 +509,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
     /**
      * 文本对齐选项
      *
-     * @param   style       对齐方式
+     * @param   value       对齐方式
      */
     private setTextAlign(value: STextAlign): void {
         // TODO: 找原因,去下边一行

+ 5 - 0
saga-web-draw/src/engines/SPaintState.ts

@@ -1,4 +1,5 @@
 import { SBrush, SFont, SPen } from "..";
+import { SCompositeType } from "../enums/SCompositeType";
 
 /**
  * 绘制状态
@@ -36,6 +37,9 @@ export class SPaintState {
         this._font = value;
     } // Set font
 
+    /** 融合 */
+    _composite = SCompositeType.SourceOver;
+
     /**
      * 构造函数
      */
@@ -44,6 +48,7 @@ export class SPaintState {
             this.pen = new SPen(state.pen);
             this.brush = new SBrush(state.brush);
             this.font = new SFont(state.font);
+            this._composite = state._composite;
             let m = new DOMMatrix();
             m.m11 = state.matrix.m11;
             m.m12 = state.matrix.m12;

+ 29 - 0
saga-web-draw/src/enums/SCompositeType.ts

@@ -0,0 +1,29 @@
+/**
+ * 融合方式
+ *
+ * @author  郝建龙
+ */
+export enum SCompositeType {
+    /** 显示源图像。忽略目标图像。   */
+    Copy,
+    /** 在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。 */
+    DestinationAtop,
+    /** 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。  */
+    DestinationIn,
+    /** 在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。  */
+    DestinationOut,
+    /** 在源图像上方显示目标图像。   */
+    DestinationOver,
+    /** 显示源图像 + 目标图像。   */
+    Lighter,
+    /** 在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的    */
+    SourceAtop,
+    /** 在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。  */
+    SourceIn,
+    /** 在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。  */
+    SourceOut,
+    /** 默认。在目标图像上显示源图像。 */
+    SourceOver,
+    /** 使用异或操作对源图像与目标图像进行组合。    */
+    Xor
+} // Enum SCompositeType