[html] 请使用canvas画一个渐变的长方形
生活随笔
收集整理的這篇文章主要介紹了
[html] 请使用canvas画一个渐变的长方形
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
[html] 請使用canvas畫一個漸變的長方形
// 普通canvas繪圖工具類// umd適配多種引入方式 (function(root, factory) {if (typeof define === 'function' && define.amd) {// AMDdefine(['CanvasTool'], factory);} else if (typeof exports === 'object' && typeof module === 'object') {// Node, CommonJS之類的module.exports = factory();} else {// 瀏覽器全局變量(root 即 window)root.CanvasTool = factory();} }(window, function() {// 方法const textBreakline = Symbol('textBreakline');const validateRlues = Symbol('validateRlues');const letterSpacingText = Symbol('letterSpacingText');const setFillStyle = Symbol('setFillStyle');const setStrokeStyle = Symbol('setStrokeStyle');const setFontSize = Symbol("setFontSize");class CanvasTool {constructor(ctx, scale) {this.ctx = ctx;this.scale = scale || 1;}/*** 畫菱形* @param {Object} rhombObj 傳入菱形的參數* sx: 開始的x軸* sy: 開始的y軸* cx: 中心位置的x軸* cy: 中心位置的y軸* width: 寬度* height: 高度* bgColor: 背景色*/rhomb(rhombObj) {let { sx, sy, cx, cy, width, height, bgColor } = rhombObj;// 參數校驗規(guī)則let ruleMap = new Map([[sx, { type: 'number', param: 'sx' }],[sy, { type: 'number', param: 'sy' }],[cx, { type: 'number', param: 'cx' }],[cy, { type: 'number', param: 'cy' }],[width, { type: 'number', param: 'width' }],[height, { type: 'number', param: 'height' }],[bgColor, { type: 'string', param: 'bgColor' }]]);this[validateRlues](ruleMap);// 設置默認值sx = sx || 0;sy = sy || 0;cx = cx || 0;cy = cy || 0;bgColor = bgColor || '#fff';this.ctx.translate(cx, cy);this.ctx.rotate(45 * Math.PI / 180);// 修正畫布坐標this.ctx.translate(-cx, -cy);this.ctx.fillStyle = bgColor;this.ctx.fillRect(sx, sy, width, height);this.ctx.save();}/*** 畫直線* @param { Object } lineObj 傳入的直線對象* line 畫直線* sx: 開始x軸* sy: 開始y軸* ex: 結束x軸* ey: 結束y軸* strokeWidth: 線寬* strokeStyle: 線條樣式*/line(lineObj) {// 獲取傳入的文本對象let { sx, sy, ex, ey, strokeWidth, strokeStyle } = lineObj;// 參數校驗規(guī)則let ruleMap = new Map([[sx, { type: 'number', param: 'sx' }],[sy, { type: 'number', param: 'sy' }],[ex, { type: 'number', param: 'ex' }],[ey, { type: 'number', param: 'ey' }],[strokeWidth, { type: 'number', param: 'strokeWidth' }],[strokeStyle, { type: 'string', param: 'strokeStyle' }]]);this[validateRlues](ruleMap);// 設置默認值sx = sx || 0;sy = sy || 0;ex = ex || 100;ey = ey || 100;strokeStyle = strokeStyle || '#000';strokeWidth = strokeWidth || 2;this.ctx.beginPath();this.ctx.moveTo(sx, sy);this.ctx.lineTo(ex, ey);this[setStrokeStyle](strokeWidth, strokeStyle);this.ctx.stroke();}/*** 畫三角形* @param { Object } triangleObj 傳入的三角形對象*/triangle(triangleObj) {// 獲取傳入的三角形對象let { fx, fy, sx, sy, tx, ty, stroke, strokeWidth, strokeStyle, fill, bgColor } = triangleObj;// 參數校驗規(guī)則let ruleMap = new Map([[fx, { type: 'number', param: 'fx' }],[fy, { type: 'number', param: 'fy' }],[sx, { type: 'number', param: 'sx' }],[sy, { type: 'number', param: 'sy' }],[tx, { type: 'number', param: 'tx' }],[ty, { type: 'number', param: 'ty' }],[strokeWidth, { type: 'number', param: 'strokeWidth' }],[bgColor, { type: 'string', param: 'bgColor' }],[strokeStyle, { type: 'string', param: 'strokeStyle' }],[stroke, { type: 'boolean', param: 'stroke' }],[fill, { type: 'boolean', param: 'fill' }]]);this[validateRlues](ruleMap);// 設置默認值fx = fx || 0;fy = fy || 0;bgColor = bgColor || '#fff';strokeStyle = strokeStyle || '#000';fill = fill || false;strokeWidth = strokeWidth || 1;this.ctx.beginPath();this.ctx.moveTo(fx, fy);this.ctx.lineTo(sx, sy);this.ctx.lineTo(tx, ty);// 填充顏色fill && (this[setFillStyle](bgColor),this.ctx.fill());stroke && (this[setStrokeStyle](strokeWidth, strokeStyle),this.ctx.stroke());}/*** rect 繪制矩形的方法* @param { Object } rectObj 傳入的矩形對象* x 頁面x軸的坐標* y 頁面y軸的坐標* width 矩形的寬度* height 矩形的高度* bgColor 矩形的背景色* fill 是否填充* strokeStyle 填充邊框的顏色* stroke 是否需要邊框*/rect(rectObj) {// 獲取傳入的文本對象let { x, y, width, height, bgColor, fill, stroke, strokeStyle, strokeWidth } = rectObj;// 參數校驗規(guī)則let ruleMap = new Map([[x, { type: 'number', param: 'x' }],[y, { type: 'number', param: 'y' }],[width, { type: 'number', param: 'width' }],[height, { type: 'number', param: 'height' }],[strokeWidth, { type: 'number', param: 'strokeWidth' }],[bgColor, { type: 'string', param: 'bgColor' }],[strokeStyle, { type: 'string', param: 'strokeStyle' }],[stroke, { type: 'boolean', param: 'stroke' }],[fill, { type: 'boolean', param: 'fill' }]]);this[validateRlues](ruleMap);// 設置默認值x = x || 0;y = y || 0;bgColor = bgColor || '#fff';strokeStyle = strokeStyle || '#000';fill = fill || false;strokeWidth = strokeWidth || 1;this.ctx.rect(x, y, width, height);fill && (this[setFillStyle](bgColor),this.ctx.fill());stroke && (this[setStrokeStyle](strokeWidth, strokeStyle),this.ctx.strokeRect(x, y, width + strokeWidth, height + strokeWidth));}/*** 繪制圓角矩形* @param {number} x 圓角矩形選區(qū)的左上角 x坐標* @param {number} y 圓角矩形選區(qū)的左上角 y坐標* @param {number} w 圓角矩形選區(qū)的寬度* @param {number} h 圓角矩形選區(qū)的高度* @param {number} r 圓角的半徑* @memberof CanvasTool*/roundRect(roundRectObj) {let { x, y, width: w, height: h, r, bgColor } = roundRectObj;// 參數校驗規(guī)則let ruleMap = new Map([[x, { type: 'number', param: 'x' }],[y, { type: 'number', param: 'y' }],[w, { type: 'number', param: 'width' }],[h, { type: 'number', param: 'height' }],[r, { type: 'number', param: 'r' }],[bgColor, { type: 'string', param: 'bgColor' }]]);this[validateRlues](ruleMap);// 開始繪制this.ctx.beginPath();this[setFillStyle](bgColor),// 左上角this.ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);// border-topthis.ctx.moveTo(x + r, y);this.ctx.lineTo(x + w - r, y);this.ctx.lineTo(x + w, y + r);// 右上角this.ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2);// border-rightthis.ctx.lineTo(x + w, y + h - r);this.ctx.lineTo(x + w - r, y + h);// 右下角this.ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5);// border-bottomthis.ctx.lineTo(x + r, y + h);this.ctx.lineTo(x, y + h - r);// 左下角this.ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI);// border-leftthis.ctx.lineTo(x, y + r);this.ctx.lineTo(x + r, y);this.ctx.fill();};/*** square 繪制正方形的方法* @param { Object } squareObj 傳入的圓形對象* 參數同矩形的參數一致,只需要傳入width就可以了*/square(squareObj) {squareObj.height = squareObj.width;this.rect(squareObj);}/*** arc 繪制圓形的方法* @param { Object } arcObj 傳入的圓形對象* x 圓心的x軸* y 圓心的y軸* r 半徑* sAngle 開始弧度* eAngle 終止弧度* counterclockwise 弧度方向是否是逆時針* fill 是否填充* storke 是有邊框* bgColor 背景色* strokeStyle 邊框色*/arc(arcObj) {let { x, y, r, sAngle, eAngle, counterclockwise, fill, bgColor, strokeStyle, strokeWidth, storke } = arcObj;// 參數校驗規(guī)則let ruleMap = new Map([[x, { type: 'number', param: 'x' }],[y, { type: 'number', param: 'y' }],[r, { type: 'number', param: 'r' }],[sAngle, { type: 'number', param: 'sAngle' }],[eAngle, { type: 'number', param: 'eAngle' }],[strokeWidth, { type: 'number', param: 'strokeWidth' }],[counterclockwise, { type: 'number', param: 'counterclockwise' }],[fill, { type: 'boolean', param: 'fill' }],[storke, { type: 'boolean', param: 'storke' }],[bgColor, { type: 'string', params: 'bgColor' }],[strokeStyle, { type: 'string', params: 'strokeStyle' }],]);this[validateRlues](ruleMap);// 設置默認值x = x || 0;y = y || 0;sAngle = sAngle || 0;eAngle = eAngle || 0;fill = fill || false;bgColor = bgColor || '#000';this.ctx.beginPath();this.ctx.arc(x, y, r, sAngle * Math.PI, eAngle * Math.PI, counterclockwise);// 圓的邊框暫時不生效storke && (this[setStrokeStyle](strokeWidth, strokeStyle),this.ctx.stroke());fill && (this[setFillStyle](bgColor),this.ctx.fill());}/*** 繪制圓形頭像* @param img 圖片資源* @param opts 參數* @param beforeFn 函數鉤子* @param afterFn 函數鉤子*/circleAvatar(circleAvatarObj) {let { img, opts, beforeFn, afterFn } = circleAvatarObj;let { x, y, r } = opts;// 參數校驗規(guī)則let ruleMap = new Map([[x, { type: 'number', param: 'x' }],[y, { type: 'number', param: 'y' }],[r, { type: 'number', param: 'r' }]]);this[validateRlues](ruleMap);(isFunction(beforeFn)) && beforeFn();this.drawCircle({x,y,r});ctx.clip();ctx.drawImage(img, x, y, r);ctx.restore();(isFunction(afterFn)) && afterFn();return this;}/*** text 繪制文本的方法 * text 文本* x 頁面x軸坐標* y 頁面y軸坐標* width 文本的最大寬度* color 顏色* fontSize 字號* align 對其方式* textBaseline 文本的基線* wrap 是否換行* lineHeight 行高* letterSpacing 字間距*/text(textObj) {// 獲取傳入的文本對象let { text, color, fontSize, fontStyle, align, x, y, width, textBaseline, wrap, lineHeight, letterSpacing } = textObj;// 參數校驗規(guī)則let ruleMap = new Map([[text, { type: 'string', param: 'text' }],[color, { type: 'string', param: 'color' }],[textBaseline, { type: 'string', param: 'textBaseline' }],[align, { type: 'string', param: 'align' }],[fontStyle, { type: 'string', param: 'fontStyle' }],[fontSize, { type: 'number', param: 'fontSize' }],[x, { type: 'number', param: 'x' }],[y, { type: 'number', param: 'y' }],[width, { type: 'number', param: 'width' }],[lineHeight, { type: 'number', param: 'lineHeight' }],[letterSpacing, { type: 'number', param: 'letterSpacing' }],[wrap, { type: 'boolean', param: 'wrap' }],]);this[validateRlues](ruleMap);// 設置默認值color = color || '';fontSize = fontSize || 16;align = align || 'center';x = x || 0;y = y || 0;width = width || 0;wrap = wrap || false; // 默認不換行l(wèi)etterSpacing = letterSpacing || 0;// 繪圖this[setFillStyle](color);this[setFontSize](fontSize * this.scale);this.ctx.textAlign = align;textBaseline && (this.ctx.setTextBaseline = textBaseline);!wrap && !letterSpacing && this.ctx.fillText(text, x, y, width);wrap && this[textBreakline](text, x, y, width, lineHeight);letterSpacing && this[letterSpacingText](text, align, x, y, letterSpacing);}// -------私有屬性--------/*** 設置填充顏色*/[setFillStyle](fillStyle) {this.ctx.fillStyle = fillStyle;}/*** 設置邊框顏色 / 寬度*/[setStrokeStyle](strokeWidth, strokeStyle) {this.ctx.lineWidth = strokeWidth;this.ctx.strokeStyle = strokeStyle;}/*** 設置字體大小*/[setFontSize](fontSize, fontStyle = "Microsoft YaHei") {console.log(fontSize, fontStyle);this.ctx.font = `${fontSize}px ${fontStyle}`;}/*** textBreakline 文本換行功能,支持行高* @param {String} text 文本* @param {Number} x 頁面x軸的位置* @param {Number} y 頁面y軸的位置* @param {Number} maxWidth 最大寬度* @param {Number} lineHeight 行高*/[textBreakline](text, x, y, maxWidth, lineHeight) {// 字符分隔為數組let arrText = text.split('');let line = '';for (let n = 0; n < arrText.length; n++) {let testLine = line + arrText[n];let metrics = this.ctx.measureText(testLine);let testWidth = metrics.width;if (testWidth > maxWidth && n > 0) {this.ctx.fillText(line, x, y);line = arrText[n];y += lineHeight;} else {line = testLine;}}this.ctx.fillText(line, x, y);}/*** 文本支持字間距* @param {String} text 文本* @param {Number} x 頁面x軸的位置* @param {Number} y 頁面y軸的位置* @param {Number} letterSpacing 字間距*/[letterSpacingText](text, textAlign, x, y, letterSpacing) {let context = this.ctx;// let canvas = context.canvas;// if (!letterSpacing && canvas) {// letterSpacing = parseFloat(window.getComputedStyle(canvas).letterSpacing);// }// if (!letterSpacing) {// return this.fillText(text, x, y);// }let arrText = text.split('');let align = textAlign || 'left';// 這里僅考水平排列l(wèi)et originWidth = context.measureText(text).width;// 應用letterSpacing占據寬度let actualWidth = originWidth + letterSpacing * (arrText.length - 1);// 根據水平對齊方式確定第一個字符的坐標if (align == 'center') {x = x - actualWidth / 2;} else if (align == 'right') {x = x - actualWidth;}// 臨時修改為文本左對齊context.textAlign = 'left';// 開始逐字繪制arrText.forEach(function(letter) {let letterWidth = context.measureText(letter).width;context.fillText(letter, x, y);// 確定下一個字符的橫坐標x = x + letterWidth + letterSpacing;});// 對齊方式還原context.textAlign = align;}// 校驗功能[validateRlues](ruleMap) {try {for (let [key, val] of ruleMap.entries()) {if (key && typeof key != val.type) {throw new Error(val.param + '的參數類型錯誤,要求是' + val.type + '類型');// 把所有參數都校驗一遍continue;}}} catch (err) {console.error(err);}}}// 暴露公共方法return CanvasTool; }));個人簡介
我是歌謠,歡迎和大家一起交流前后端知識。放棄很容易,
但堅持一定很酷。歡迎大家一起討論
主目錄
與歌謠一起通關前端面試題
總結
以上是生活随笔為你收集整理的[html] 请使用canvas画一个渐变的长方形的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CenterCrop的Video Vie
- 下一篇: houseparty不流畅_重新设计Ho