宅男在线永久免费观看网直播,亚洲欧洲日产国码无码久久99,野花社区在线观看视频,亚洲人交乣女bbw,一本一本久久a久久精品综合不卡

全部
常見問題
產(chǎn)品動(dòng)態(tài)
精選推薦

Fabric.js 學(xué)習(xí)筆記,快速上手

管理 管理 編輯 刪除

Fabric.js 是一個(gè)強(qiáng)大的、靈活的 HTML5 畫布庫。

1. Fabric

在 Fabric.js 中,preserveObjectStacking 屬性是一個(gè)布爾值,用于控制當(dāng)對(duì)象被修改(例如移動(dòng)、旋轉(zhuǎn)、縮放等)時(shí),它們?cè)诙褩V械奈恢檬欠癖3植蛔儭?/p>

設(shè)置 preserveObjectStacking 屬性,你可以在創(chuàng)建 fabric.Canvas 實(shí)例時(shí)指定它:


var canvas = new fabric.Canvas('c', {
   preserveObjectStacking: true
});

或者,你可以在任何時(shí)候通過以下方式更改現(xiàn)有 canvas 的 preserveObjectStacking 屬性:


canvas.preserveObjectStacking = true;
canvas.renderAll(); // 重新渲染畫布以應(yīng)用更改

常用方法如下:

  • add(obj): 向畫布添加一個(gè)或多個(gè)對(duì)象(如矩形、圓形、文本、圖像等)。
  • remove(obj): 從畫布中移除一個(gè)對(duì)象。
  • getObjects(): 返回畫布上所有對(duì)象的數(shù)組。
  • setActiveObject(obj): 設(shè)置當(dāng)前活動(dòng)的(即選中的)對(duì)象。
  • getActiveObject(): 獲取當(dāng)前活動(dòng)的(選中的)對(duì)象。
  • clear(): 清除畫布上的所有對(duì)象,但不銷毀它們。
  • renderAll(): 重新渲染畫布上的所有對(duì)象。
  • toDataURL([options]): 將畫布上的內(nèi)容導(dǎo)出為一個(gè)數(shù)據(jù) URL。
  • toJSON([options]): 將畫布上的對(duì)象序列化為 JSON 字符串。
  • loadFromJSON(json, callback): 從 JSON 字符串加載對(duì)象到畫布。
  • getActiveObjects(): 獲取當(dāng)前選中的一組對(duì)象(fabric.ActiveSelection 實(shí)例)。
  • deactivateAll(): 取消所有對(duì)象的活動(dòng)狀態(tài)。
  • discardActiveObject(): 銷毀當(dāng)前活動(dòng)的(選中的)對(duì)象。
  • sendToBack(obj): 將對(duì)象發(fā)送到畫布的最后層。
  • bringToFront(obj): 將對(duì)象帶到畫布的最前層。
  • sendBackwards(obj): 將對(duì)象向后發(fā)送一層。
  • bringForward(obj): 將對(duì)象向前移動(dòng)一層。
  • getSelectionStyles(): 獲取當(dāng)前選中對(duì)象的樣式。
  • setSelectionStyles(styles): 設(shè)置當(dāng)前選中對(duì)象的樣式。
  • setDimensions(width, height): 設(shè)置畫布的尺寸。
  • getCenter(): 獲取畫布的中心點(diǎn)坐標(biāo)。
  • calcOffset(): 計(jì)算畫布的偏移量。
  • on(type, listener): 為畫布綁定事件監(jiān)聽器。
  • off(type, listener): 移除畫布上的事件監(jiān)聽器。
  • fire(type, options): 觸發(fā)畫布上的事件。
  • dispose(): 銷毀畫布實(shí)例,釋放資源。
  • clone(): 克隆畫布實(shí)例。
  • toDatalessJSON([options]): 序列化畫布對(duì)象,但不包括事件監(jiān)聽器和非序列化屬性。
  • setBackground(color, callback): 設(shè)置畫布的背景顏色。
  • getBackgroundColor(): 獲取畫布的背景顏色。

2. 圖形

fabric.image屬性列表如下:

  • element: null - 一個(gè) Image 元素或其實(shí)例,用作圖像的源。
  • src: null - 圖像的源 URL。
  • width: 根據(jù)圖像或 element 確定 - 圖像的寬度。
  • height: 根據(jù)圖像或 element 確定 - 圖像的高度。
  • selectable: true - 表示圖像是否可以被選擇。
  • hasControls: true - 表示是否顯示控制點(diǎn)以便進(jìn)行變換操作。
  • hasRotatingPoint: false - 表示是否顯示旋轉(zhuǎn)控制點(diǎn)。
  • lockRotation: false - 阻止圖像旋轉(zhuǎn)。
  • lockScalingX: false - 阻止沿 X 軸縮放。
  • lockScalingY: false - 阻止沿 Y 軸縮放。
  • lockMovement: false - 阻止圖像移動(dòng)。
  • scaleX: 1 - 沿 X 軸的縮放因子。
  • scaleY: 1 - 沿 Y 軸的縮放因子。
  • flipX: false - 是否沿 X 軸翻轉(zhuǎn)圖像。
  • flipY: false - 是否沿 Y 軸翻轉(zhuǎn)圖像。
  • opacity: 1 - 圖像的不透明度。
  • angle: 0 - 圖像的旋轉(zhuǎn)角度。
  • originX: 'left' - 縮放和旋轉(zhuǎn)的原點(diǎn)在 X 軸上的位置。
  • originY: 'top' - 縮放和旋轉(zhuǎn)的原點(diǎn)在 Y 軸上的位置。
  • crossOrigin: false - 是否設(shè)置跨域資源共享。
  • alignX: 根據(jù)圖像寬度確定 - 水平對(duì)齊方式。
  • alignY: 根據(jù)圖像高度確定 - 垂直對(duì)齊方式。
  • meetOrSlice: false - 是否裁剪圖像以適應(yīng) width 和 height。

常用方法:

  • getSrc(): 返回圖像的源 URL。
  • setSrc(src): 設(shè)置圖像的新源 URL 并重新加載圖像。
  • getElement(): 返回圖像的 DOM 元素。
  • setImage(imageUrl, [callback]): 設(shè)置圖像的源,并在加載完成后可選地調(diào)用回調(diào)函數(shù)。
  • crossOrigin: 設(shè)置為 true 以啟用跨域圖像加載。
  • toDataURL([options]): 將圖像轉(zhuǎn)換為數(shù)據(jù) URL。
  • toDataURLWithMultiplier([multiplier], [callback]): 將圖像轉(zhuǎn)換為數(shù)據(jù) URL,并允許指定縮放因子。
  • clone(): 創(chuàng)建并返回當(dāng)前圖像對(duì)象的深拷貝。
  • toJSON(): 序列化圖像對(duì)象為 JSON 字符串。
  • setAngle(angle): 設(shè)置圖像的旋轉(zhuǎn)角度。
  • setOpacity(opacity): 設(shè)置圖像的不透明度。
  • setFlipX(flipX): 沿 X 軸翻轉(zhuǎn)圖像。
  • setFlipY(flipY): 沿 Y 軸翻轉(zhuǎn)圖像。
  • scale(scaleX, scaleY): 縮放圖像。
  • skew(skewX, skewY): 對(duì)圖像進(jìn)行傾斜變換。
  • rotate(angle): 旋轉(zhuǎn)圖像。
  • scaleToWidth(width): 根據(jù)給定的寬度縮放圖像。
  • scaleToHeight(height): 根據(jù)給定的高度縮放圖像。
  • setWidth(width): 設(shè)置圖像的寬度。
  • setHeight(height): 設(shè)置圖像的高度。
  • setPosition({ left, top }): 設(shè)置圖像的位置。
  • setSelectabe(selectable): 設(shè)置圖像是否可選中。
  • setHasControls(hasControls): 設(shè)置圖像是否顯示控制點(diǎn)。
  • setOriginX(originX): 設(shè)置圖像旋轉(zhuǎn)和縮放的 X 軸原點(diǎn)。
  • setOriginY(originY): 設(shè)置圖像旋轉(zhuǎn)和縮放的 Y 軸原點(diǎn)。
  • setStroke(stroke): 設(shè)置圖像邊框的顏色。
  • setStrokeWidth(strokeWidth): 設(shè)置圖像邊框的寬度。
  • setBackgroundColor(backgroundColor): 設(shè)置圖像的背景顏色。
  • setFill(fill): 設(shè)置圖像的填充顏色。
  • setStrokeDashArray(strokeDashArray): 設(shè)置圖像邊框的虛線樣式。
  • setTransformMatrix(matrix): 應(yīng)用一個(gè)變換矩陣到圖像上。
  • setVisible(visible): 設(shè)置圖像是否可見。
  • bringToFront(): 將圖像移動(dòng)到畫布的最上層。
  • sendToBack(): 將圖像移動(dòng)到畫布的最下層。
  • moveUp(): 將圖像向上移動(dòng)一層。
  • moveDown(): 將圖像向下移動(dòng)一層。
  • remove(): 從畫布上移除圖像。

3. 問題記錄

  1. EraserBrush不是 Fabric 默認(rèn)構(gòu)建的一部分

4. 涂抹

設(shè)置擦除,圖形的erasable為true時(shí)可擦除:


// 鉛筆筆刷
canvas.freeDrawingBrush = new fabric.PencilBrush(canvas);
canvas.freeDrawingBrush.width = 30;
canvas.freeDrawingBrush.color = 'rgb(255, 0, 0, 0.3)';
canvas.isDrawingMode = true;
canvas.freeDrawingCursor = 'none';

const cursor = new fabric.Circle({
  radius: 0,
  fill: 'rgb(255, 0, 0, 0.3)',
  left: 0,
  top: 0,
  erasable: false,
  selectable: false,
  evented: false,
  visible: false,
});

canvas.add(cursor);
canvas.bringToFront(cursor);

/* 設(shè)置鼠標(biāo)樣式 */
cursor.set('fill', 'rgb(255, 0, 0, 0.3)');
cursor.set({strokeWidth: 0.1, stroke: 'rgba(255, 0, 0, 0.3)'});
cursor.set('radius', 15);

/* 每次涂抹處理路徑控制屬性 */
canvas.on('path:created', (e) => {
  cursor.toolbarChecked = val;
  cursor.toolbarCheckedValue = 15;
  e.path.set('selectable', false);
  e.path.set('evented', false);
  canvas.renderAll();
});

5. 擦除


// 鉛筆筆刷
canvas.freeDrawingBrush = new fabric.EraserBrush(canvas);
canvas.freeDrawingBrush.width = 30;
canvas.freeDrawingBrush.color = 'rgb(255, 0, 0, 0.3)';
canvas.isDrawingMode = true;
canvas.freeDrawingCursor = 'none';

const cursor = new fabric.Circle({
  radius: 0,
  fill: 'rgb(255, 0, 0, 0.3)',
  left: 0,
  top: 0,
  erasable: false,
  selectable: false,
  evented: false,
  visible: false,
});

canvas.add(cursor);
canvas.bringToFront(cursor);

/* 設(shè)置鼠標(biāo)樣式 */
cursor.set('fill', 'rgb(255, 0, 0, 0.3)');
cursor.set({strokeWidth: 0.1, stroke: 'rgba(255, 0, 0, 0.3)'});
cursor.set('radius', 15);

/* 每次涂抹處理路徑控制屬性 */
canvas.on('path:created', (e) => {
  cursor.toolbarChecked = val;
  cursor.toolbarCheckedValue = 15;
  e.path.set('selectable', false);
  e.path.set('evented', false);
  canvas.renderAll();
});

5. 自定義Control的樣式


import { fabric } from 'fabric';
import verticalImg from '@/assets/middlecontrol.svg?url';
import horizontalImg from '@/assets/middlecontrolhoz.svg?url';
import edgeImg from '@/assets/edgecontrol.svg?url';
import rotateImg from '@/assets/rotateicon.svg?url';

/**
 * 實(shí)際場(chǎng)景: 在進(jìn)行某個(gè)對(duì)象縮放的時(shí)候,由于fabricjs默認(rèn)精度使用的是toFixed(2)。
 * 此處為了縮放的精度更準(zhǔn)確一些,因此將NUM_FRACTION_DIGITS默認(rèn)值改為4,即toFixed(4).
 */
fabric.Object.NUM_FRACTION_DIGITS = 4;

const verticalImgIcon = document.createElement('img');
verticalImgIcon.src = verticalImg;

const horizontalImgIcon = document.createElement('img');
horizontalImgIcon.src = horizontalImg;

const edgeImgIcon = document.createElement('img');
edgeImgIcon.src = edgeImg;

const rotateImgIcon = document.createElement('img');
rotateImgIcon.src = rotateImg;

// 繪制圖像函數(shù)
function drawImg(ctx, left, top, img, wSize, hSize, angle) {
  if (angle === undefined) return;
  ctx.save();
  ctx.translate(left, top);
  ctx.rotate(fabric.util.degreesToRadians(angle));
  ctx.drawImage(img, -wSize / 2, -hSize / 2, wSize, hSize);
  ctx.restore();
}

// 中間橫杠
function intervalControl() {
  function renderIcon(ctx, left, top, styleOverride, fabricObject) {
    drawImg(ctx, left, top, verticalImgIcon, 20, 25, fabricObject.angle);
  }

  function renderIconHoz(ctx, left, top, styleOverride, fabricObject) {
    drawImg(ctx, left, top, horizontalImgIcon, 25, 20, fabricObject.angle);
  }

  // 中間橫杠
  fabric.Object.prototype.controls.ml = new fabric.Control({
    x: -0.5,
    y: 0,
    offsetX: -1,
    cursorStyleHandler: fabric.controlsUtils.scaleSkewCursorStyleHandler,
    actionHandler: fabric.controlsUtils.scalingXOrSkewingY,
    getActionName: fabric.controlsUtils.scaleOrSkewActionName,
    render: renderIcon,
  });

  fabric.Object.prototype.controls.mr = new fabric.Control({
    x: 0.5,
    y: 0,
    offsetX: 1,
    cursorStyleHandler: fabric.controlsUtils.scaleSkewCursorStyleHandler,
    actionHandler: fabric.controlsUtils.scalingXOrSkewingY,
    getActionName: fabric.controlsUtils.scaleOrSkewActionName,
    render: renderIcon,
  });

  fabric.Object.prototype.controls.mb = new fabric.Control({
    x: 0,
    y: 0.5,
    offsetY: 1,
    cursorStyleHandler: fabric.controlsUtils.scaleSkewCursorStyleHandler,
    actionHandler: fabric.controlsUtils.scalingYOrSkewingX,
    getActionName: fabric.controlsUtils.scaleOrSkewActionName,
    render: renderIconHoz,
  });

  fabric.Object.prototype.controls.mt = new fabric.Control({
    x: 0,
    y: -0.5,
    offsetY: -1,
    cursorStyleHandler: fabric.controlsUtils.scaleSkewCursorStyleHandler,
    actionHandler: fabric.controlsUtils.scalingYOrSkewingX,
    getActionName: fabric.controlsUtils.scaleOrSkewActionName,
    render: renderIconHoz,
  });
}

// 頂點(diǎn)
function peakControl() {
  function renderIconEdge(ctx, left, top, styleOverride, fabricObject) {
    drawImg(ctx, left, top, edgeImgIcon, 25, 25, fabricObject.angle);
  }

  // 四角圖標(biāo)
  fabric.Object.prototype.controls.tl = new fabric.Control({
    x: -0.5,
    y: -0.5,
    cursorStyleHandler: fabric.controlsUtils.scaleCursorStyleHandler,
    actionHandler: fabric.controlsUtils.scalingEqually,
    render: renderIconEdge,
  });
  fabric.Object.prototype.controls.bl = new fabric.Control({
    x: -0.5,
    y: 0.5,
    cursorStyleHandler: fabric.controlsUtils.scaleCursorStyleHandler,
    actionHandler: fabric.controlsUtils.scalingEqually,
    render: renderIconEdge,
  });
  fabric.Object.prototype.controls.tr = new fabric.Control({
    x: 0.5,
    y: -0.5,
    cursorStyleHandler: fabric.controlsUtils.scaleCursorStyleHandler,
    actionHandler: fabric.controlsUtils.scalingEqually,
    render: renderIconEdge,
  });
  fabric.Object.prototype.controls.br = new fabric.Control({
    x: 0.5,
    y: 0.5,
    cursorStyleHandler: fabric.controlsUtils.scaleCursorStyleHandler,
    actionHandler: fabric.controlsUtils.scalingEqually,
    render: renderIconEdge,
  });
}

// 旋轉(zhuǎn)
function rotationControl() {
  function renderIconRotate(ctx, left, top, styleOverride, fabricObject) {
    drawImg(ctx, left, top, rotateImgIcon, 40, 40, fabricObject.angle);
  }

  // 旋轉(zhuǎn)圖標(biāo)
  fabric.Object.prototype.controls.mtr = new fabric.Control({
    x: 0,
    y: 0.5,
    cursorStyleHandler: fabric.controlsUtils.rotationStyleHandler,
    actionHandler: fabric.controlsUtils.rotationWithSnapping,
    offsetY: 30,
    // withConnecton: false,
    actionName: 'rotate',
    render: renderIconRotate,
  });
}

export default function initControl() {
  // 頂點(diǎn)圖標(biāo)
  peakControl();
  // 中間橫杠圖標(biāo)
  intervalControl();
  // 旋轉(zhuǎn)圖標(biāo)
  rotationControl();

  fabric.Object.prototype.set({
    transparentCorners: false,
    borderColor: '#51B9F9',
    cornerColor: '#FFF',
    borderScaleFactor: 2.5,
    cornerStyle: 'circle',
    cornerStrokeColor: '#0E98FC',
    borderOpacityWhenMoving: 1,
  });
}


請(qǐng)登錄后查看

小碼二開 最后編輯于2024-09-02 10:48:25

快捷回復(fù)
回復(fù)
回復(fù)
回復(fù)({{post_count}}) {{!is_user ? '我的回復(fù)' :'全部回復(fù)'}}
排序 默認(rèn)正序 回復(fù)倒序 點(diǎn)贊倒序

{{item.user_info.nickname ? item.user_info.nickname : item.user_name}} LV.{{ item.user_info.bbs_level || item.bbs_level }}

作者 管理員 企業(yè)

{{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest == 1? '取消推薦': '推薦'}}
{{item.is_suggest == 1? '取消推薦': '推薦'}}
沙發(fā) 板凳 地板 {{item.floor}}#
{{item.user_info.title || '暫無簡(jiǎn)介'}}
附件

{{itemf.name}}

{{item.created_at}}  {{item.ip_address}}
打賞
已打賞¥{{item.reward_price}}
{{item.like_count}}
{{item.showReply ? '取消回復(fù)' : '回復(fù)'}}
刪除
回復(fù)
回復(fù)

{{itemc.user_info.nickname}}

{{itemc.user_name}}

回復(fù) {{itemc.comment_user_info.nickname}}

附件

{{itemf.name}}

{{itemc.created_at}}
打賞
已打賞¥{{itemc.reward_price}}
{{itemc.like_count}}
{{itemc.showReply ? '取消回復(fù)' : '回復(fù)'}}
刪除
回復(fù)
回復(fù)
查看更多
打賞
已打賞¥{{reward_price}}
2755
{{like_count}}
{{collect_count}}
添加回復(fù) ({{post_count}})

相關(guān)推薦

快速安全登錄

使用微信掃碼登錄
{{item.label}} 加精
{{item.label}} {{item.label}} 板塊推薦 常見問題 產(chǎn)品動(dòng)態(tài) 精選推薦 首頁頭條 首頁動(dòng)態(tài) 首頁推薦
取 消 確 定
回復(fù)
回復(fù)
問題:
問題自動(dòng)獲取的帖子內(nèi)容,不準(zhǔn)確時(shí)需要手動(dòng)修改. [獲取答案]
答案:
提交
bug 需求 取 消 確 定
打賞金額
當(dāng)前余額:¥{{rewardUserInfo.reward_price}}
{{item.price}}元
請(qǐng)輸入 0.1-{{reward_max_price}} 范圍內(nèi)的數(shù)值
打賞成功
¥{{price}}
完成 確認(rèn)打賞

微信登錄/注冊(cè)

切換手機(jī)號(hào)登錄

{{ bind_phone ? '綁定手機(jī)' : '手機(jī)登錄'}}

{{codeText}}
切換微信登錄/注冊(cè)
暫不綁定
CRMEB客服

CRMEB咨詢熱線 咨詢熱線

400-8888-794

微信掃碼咨詢

CRMEB開源商城下載 源碼下載 CRMEB幫助文檔 幫助文檔
返回頂部 返回頂部
CRMEB客服