在做組態的時候,需要支持矩形圓角格式,但是因為canvas本身不帶有圓角矩形,需要自行算出坐標進行繪制
方案一、統一圓角
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>canvas制作圓角矩形(包括填充矩形的功能)</title> </head> <body> <canvas id="myCanvas" style="border:1px solid #d3d3d3;"> 您的瀏覽器不支持 HTML5 canvas 標簽。</canvas> <script> window.onload = function() { var myCanvas = document.getElementById("myCanvas"); //獲取canvas對象 if (myCanvas.getContext("2d")) { //判斷瀏覽器是否支持canvas標簽 //設置canvas的寬度和高度 myCanvas.width = 400; myCanvas.height = 200; var context = myCanvas.getContext("2d"); //獲取畫布context的上下文環境 //繪制一個圓角矩形 strokeRoundRect(context, 10, 10, 100, 50, 10); //繪制並填充一個圓角矩形 fillRoundRect(context, 200, 10, 100, 50, 10, 'rgba(0,0,0,0.7)'); } else { alert("您的瀏覽器不支持canvas,請換個瀏覽器試試"); } }; /**該方法用來繪制一個有填充色的圓角矩形 *@param cxt:canvas的上下文環境 *@param x:左上角x軸坐標 *@param y:左上角y軸坐標 *@param width:矩形的寬度 *@param height:矩形的高度 *@param radius:圓的半徑 *@param fillColor:填充顏色 **/ function fillRoundRect(cxt, x, y, width, height, radius, /*optional*/ fillColor) { //圓的直徑必然要小於矩形的寬高 if (2 * radius > width || 2 * radius > height) { return false; } cxt.save(); cxt.translate(x, y); //繪制圓角矩形的各個邊 drawRoundRectPath(cxt, width, height, radius); cxt.fillStyle = fillColor || "#000"; //若是給定了值就用給定的值否則給予默認值 cxt.fill(); cxt.restore(); } /**該方法用來繪制圓角矩形 *@param cxt:canvas的上下文環境 *@param x:左上角x軸坐標 *@param y:左上角y軸坐標 *@param width:矩形的寬度 *@param height:矩形的高度 *@param radius:圓的半徑 *@param lineWidth:線條粗細 *@param strokeColor:線條顏色 **/ function strokeRoundRect(cxt, x, y, width, height, radius, /*optional*/ lineWidth, /*optional*/ strokeColor) { //圓的直徑必然要小於矩形的寬高 if (2 * radius > width || 2 * radius > height) { return false; } cxt.save(); cxt.translate(x, y); //繪制圓角矩形的各個邊 drawRoundRectPath(cxt, width, height, radius); cxt.lineWidth = lineWidth || 2; //若是給定了值就用給定的值否則給予默認值2 cxt.strokeStyle = strokeColor || "#000"; cxt.stroke(); cxt.restore(); } function drawRoundRectPath(cxt, width, height, radius) { cxt.beginPath(0); //從右下角順時針繪制,弧度從0到1/2PI cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2); //矩形下邊線 cxt.lineTo(radius, height); //左下角圓弧,弧度從1/2PI到PI cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI); //矩形左邊線 cxt.lineTo(0, radius); //左上角圓弧,弧度從PI到3/2PI cxt.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2); //上邊線 cxt.lineTo(width - radius, 0); //右上角圓弧 cxt.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2); //右邊線 cxt.lineTo(width, height - radius); cxt.closePath(); } </script> </body> </html>
效果圖
方案二、支持多種圓角格式【右下、左下、左上、右上】
申明一個變量,以數組的形式,然后將 drawRoundRectPath函數重新改寫一下即可
drawRoundRectPath(cxt, width, height) { var radius = this.radius;//vue data里面的數據 var r0 = radius[0],r1 = radius[1],r2 = radius[2],r3 = radius[3]; cxt.beginPath(0); //從右下角順時針繪制,弧度從0到1/2PI cxt.arc(width - r0, height - r0, r0, 0, Math.PI / 2); //矩形下邊線 cxt.lineTo(r1, height); //左下角圓弧,弧度從1/2PI到PI cxt.arc(r1, height - r1, r1, Math.PI / 2, Math.PI); //矩形左邊線 cxt.lineTo(0, r2); //左上角圓弧,弧度從PI到3/2PI cxt.arc(r2, r2, r2, Math.PI, Math.PI * 3 / 2); //上邊線 cxt.lineTo(width - r3, 0); //右上角圓弧 cxt.arc(width - r3, r3, r3, Math.PI * 3 / 2, Math.PI * 2); //右邊線 cxt.lineTo(width, height - r3); cxt.closePath(); }
實例
vue進行繪制矩形

<template> <canvas :id="options.id" ref="canvas" class="elem-container" :width="canvasWidth" :height="canvasHeight" :style="assignStyle" /> </template> <script> import mixins from './canvasMixins.js' export default { name: 'RectElem', mixins: [mixins], data() { return { myOptions: { penStyle: 0 }, assignStyle: {} // 合並樣式 } }, computed: { 'canvasWidth': function() { return (parseFloat(this.myOptions.width) + parseFloat(this.myOptions.borderWidth)) }, 'canvasHeight': function() { return (parseFloat(this.myOptions.height) + parseFloat(this.myOptions.borderWidth)) }, 'radius' : function(){ debugger; if(this.myOptions.radius == "none"){ return [0,0,0,0]} return !!this.myOptions.radius ? JSON.parse(this.myOptions.radius) : [0,0,0,0] } }, mounted() { this.initialStyleOfRec() }, methods: { initialStyleOfRec() { const options = this.myOptions // 父組件傳入的參數 const bWidth = options.borderWidth let baseStyle = options.style // 未轉為對象前的基礎樣式(字符串) const width = options.width ? `width:${options.borderWidth ? (options.width * 1 + options.borderWidth) : options.width}px;` : '' const height = options.height ? `height:${options.borderWidth ? (options.height * 1 + options.borderWidth) : options.height}px;` : '' const len = baseStyle.length baseStyle = baseStyle.charAt(len - 1) === ';' ? (baseStyle + width + height) : (baseStyle + ';' + width + height) this.baseStyle = this.style2Object(baseStyle) if (bWidth && bWidth !== '') { this.baseStyle.top = `${-0.5 * (this.options.borderWidth || 0)}px` this.baseStyle.left = `${-0.5 * (this.options.borderWidth || 0)}px` } this.assignStyle = this.baseStyle }, // // 把字符串樣式轉化為{} // styleToObject(style) { // let styleObject = {} // if (style && style !== '' && style !== 'null') { // const len = style.length // styleObject = style.charAt(len - 1) === ';' ? '{' + style + '}' : '{' + style + ';}' // 統一樣式后面以";"結束 // // 將字符串轉化為json標准字符串 // styleObject = styleObject.replace(/{/g, '{\"') // styleObject = styleObject.replace(/:/g, '\":\"') // styleObject = styleObject.replace(/;/g, '\",\"') // styleObject = styleObject.replace(/,"}/g, '}') // // 將json標准字符串轉化為{}對象 // styleObject = JSON.parse(styleObject) // } // return styleObject // }, render(options) { const ctx = this.getCleanCtx()// 獲取canvas畫布 const penStyle = options.penStyle// 線型 // 判斷 const halfBW = 0.5 * (options.borderWidth || 0) // 線寬的一半 const fillColor = options.fillColor if (penStyle === 0) { ctx.lineWidth === 0 } else if (penStyle !== 1) { ctx.setLineDash(this.getLineDashArr(penStyle)) } let param = { x:0 + halfBW, y:0 + halfBW, w:options.width, h:options.height, radius:options.radius || [0,0,0,0] } if (fillColor !== 'none') { // 繪制填充矩形 ctx.fillStyle = fillColor // ctx.fillRect(0 + halfBW, 0 + halfBW, options.width, options.height); //繪制填充圓角矩形 this.fillRoundRect(ctx,param); //ctx.fill() } ctx.lineWidth = options.borderWidth ctx.strokeStyle = options.borderColor //ctx.strokeRect(0 + halfBW, 0 + halfBW, options.width, options.height) //繪制描邊圓角矩形 this.strokeRoundRect(ctx,param); }, /**該方法用來繪制一個有填充色的圓角矩形 *@param cxt:canvas的上下文環境 *@param param.x:左上角x軸坐標 *@param param.y:左上角y軸坐標 *@param param.w:矩形的寬度 *@param param.h:矩形的高度 *@param param.radius:圓的半徑 **/ fillRoundRect(cxt, param) { let x = param.x, ctx = ctx, y = param.y, width = param.w, height = param.h, radius = param.radius; //圓的直徑必然要小於矩形的寬高 if (2 * radius > width || 2 * radius > height) { return false; } cxt.save(); cxt.translate(x, y); //繪制圓角矩形的各個邊 this.drawRoundRectPath(cxt, width, height, radius); //cxt.fillStyle = fillColor || "#000"; //若是給定了值就用給定的值否則給予默認值 cxt.fill(); cxt.restore(); }, drawRoundRectPath(cxt, width, height) { var radius = this.radius; var r0 = radius[0],r1 = radius[1],r2 = radius[2],r3 = radius[3]; cxt.beginPath(0); //從右下角順時針繪制,弧度從0到1/2PI cxt.arc(width - r0, height - r0, r0, 0, Math.PI / 2); //矩形下邊線 cxt.lineTo(r1, height); //左下角圓弧,弧度從1/2PI到PI cxt.arc(r1, height - r1, r1, Math.PI / 2, Math.PI); //矩形左邊線 cxt.lineTo(0, r2); //左上角圓弧,弧度從PI到3/2PI cxt.arc(r2, r2, r2, Math.PI, Math.PI * 3 / 2); //上邊線 cxt.lineTo(width - r3, 0); //右上角圓弧 cxt.arc(width - r3, r3, r3, Math.PI * 3 / 2, Math.PI * 2); //右邊線 cxt.lineTo(width, height - r3); cxt.closePath(); }, /**該方法用來繪制描邊圓角矩形 *@param cxt:canvas的上下文環境 *@param x:左上角x軸坐標 *@param y:左上角y軸坐標 *@param width:矩形的寬度 *@param height:矩形的高度 *@param radius:圓的半徑 *@param lineWidth:線條粗細 *@param strokeColor:線條顏色 **/ strokeRoundRect(cxt,param){ let x = param.x, y = param.y, width = param.w, height = param.h, radius = param.radius; //圓的直徑必然要小於矩形的寬高 if (2 * radius > width || 2 * radius > height) { return false; } cxt.save(); cxt.translate(x, y); //繪制圓角矩形的各個邊 this.drawRoundRectPath(cxt, width, height, radius); // cxt.lineWidth = lineWidth || 2; //若是給定了值就用給定的值否則給予默認值2 //cxt.strokeStyle = strokeColor || "#000"; cxt.stroke(); cxt.restore(); } } } </script>