uview-next
Version:
基于uView UI 2.0,110+高质量组件库,支持vue2和vue3,支持鸿蒙,支持多语言,搭配便捷工具助力,让开发更得心应手
155 lines (147 loc) • 5.69 kB
JavaScript
/* eslint-disable */
// 当ctx传入当前文件,const grd = ctx.createCircularGradient() 和
// const grd = this.ctx.createLinearGradient() 无效,因此只能分开处理
// 先分析,在外部创建grd,再传入使用就可以
/**
* 分析渐变字符串,提取颜色和百分比
* @param {string} string - 渐变字符串
* @returns {object} 包含colors和percents的对象
*/
function analizeGrad(string) {
const colorPercents = string.substring(0, string.length - 1).split('%,');
const colors = [];
const percents = [];
for (let colorPercent of colorPercents) {
colors.push(colorPercent.substring(0, colorPercent.lastIndexOf(' ')).trim());
percents.push(colorPercent.substring(colorPercent.lastIndexOf(' '), colorPercent.length) / 100);
}
return {
colors: colors,
percents: percents
};
}
/**
* 分析线性渐变的方向参数
* @param {string} bg - 渐变背景字符串
* @param {number} width - 宽度
* @param {number} height - 高度
* @returns {Array} 坐标数组
*/
function analizeLinear(bg, width, height) {
const direction = bg.match(/([-]?\d{1,3})deg/);
const dir = direction && direction[1] ? parseFloat(direction[1]) : 0;
let coordinate;
switch (dir) {
case 0:
coordinate = [0, -height / 2, 0, height / 2];
break;
case 90:
coordinate = [width / 2, 0, -width / 2, 0];
break;
case -90:
coordinate = [-width / 2, 0, width / 2, 0];
break;
case 180:
coordinate = [0, height / 2, 0, -height / 2];
break;
case -180:
coordinate = [0, -height / 2, 0, height / 2];
break;
default:
let x1 = 0;
let y1 = 0;
let x2 = 0;
let y2 = 0;
if (direction[1] > 0 && direction[1] < 90) {
x1 =
width / 2 -
(((width / 2) * Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) - height / 2) * Math.sin((2 * (90 - direction[1]) * Math.PI * 2) / 360)) / 2;
y2 = Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) * x1;
x2 = -x1;
y1 = -y2;
} else if (direction[1] > -180 && direction[1] < -90) {
x1 =
-(width / 2) +
(((width / 2) * Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) - height / 2) * Math.sin((2 * (90 - direction[1]) * Math.PI * 2) / 360)) / 2;
y2 = Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) * x1;
x2 = -x1;
y1 = -y2;
} else if (direction[1] > 90 && direction[1] < 180) {
x1 =
width / 2 +
((-(width / 2) * Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) - height / 2) * Math.sin((2 * (90 - direction[1]) * Math.PI * 2) / 360)) / 2;
y2 = Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) * x1;
x2 = -x1;
y1 = -y2;
} else {
x1 =
-(width / 2) -
((-(width / 2) * Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) - height / 2) * Math.sin((2 * (90 - direction[1]) * Math.PI * 2) / 360)) / 2;
y2 = Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) * x1;
x2 = -x1;
y1 = -y2;
}
coordinate = [x1, y1, x2, y2];
break;
}
return coordinate;
}
/**
* 创建径向渐变效果
* @param {number} width - 宽度
* @param {number} height - 高度
* @param {string} bg - 渐变背景字符串
* @param {CanvasRenderingContext2D} ctx - Canvas上下文
*/
function radialEffect(width, height, bg, ctx) {
const colorPer = analizeGrad(bg.match(/radial-gradient\((.+)\)/)[1]);
const grd = ctx.createRadialGradient(0, 0, 0, 0, 0, width < height ? height / 2 : width / 2);
for (let i = 0; i < colorPer.colors.length; i++) {
grd.addColorStop(colorPer.percents[i], colorPer.colors[i]);
}
ctx.fillStyle = grd;
//ctx.fillRect(-(width / 2), -(height / 2), width, height);
}
/**
* 创建线性渐变效果
* @param {number} width - 宽度
* @param {number} height - 高度
* @param {string} bg - 渐变背景字符串
* @param {CanvasRenderingContext2D} ctx - Canvas上下文
*/
function linearEffect(width, height, bg, ctx) {
const param = analizeLinear(bg, width, height);
const grd = ctx.createLinearGradient(param[0], param[1], param[2], param[3]);
const content = bg.match(/linear-gradient\((.+)\)/)[1];
const colorPer = analizeGrad(content.substring(content.indexOf(',') + 1));
for (let i = 0; i < colorPer.colors.length; i++) {
grd.addColorStop(colorPer.percents[i], colorPer.colors[i]);
}
ctx.fillStyle = grd;
//ctx.fillRect(-(width / 2), -(height / 2), width, height);
}
/**
* 判断是否为渐变背景
* @param {string} bg - 背景字符串
* @returns {boolean} 是否为渐变
*/
export function isGradient(bg) {
if (bg && (bg.startsWith('linear') || bg.startsWith('radial'))) {
return true;
}
return false;
}
/**
* 执行渐变效果
* @param {string} bg - 渐变背景字符串
* @param {number} width - 宽度
* @param {number} height - 高度
* @param {CanvasRenderingContext2D} ctx - Canvas上下文
*/
export function doGradient(bg, width, height, ctx) {
if (bg.startsWith('linear')) {
linearEffect(width, height, bg, ctx);
} else if (bg.startsWith('radial')) {
radialEffect(width, height, bg, ctx);
}
}