chore: 字体文件

This commit is contained in:
2026-02-06 16:07:16 +08:00
parent 275ec7bb97
commit 1a7c848334
13 changed files with 830 additions and 30 deletions

View File

@@ -27,7 +27,7 @@
@font-face {
font-family: 'PoppinsBold';
src: url('./Poppins-SemiBold.ttf') format('truetype');
src: url('./Poppins-SemiBold.ttf') format('ttf');
}
@font-face {

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,41 @@
/* 字体定义 */
@font-face {
font-family: 'Arial';
src: url('./ARIAL.ttf') format('truetype');
}
@font-face {
font-family: 'ArialBold';
src: url('./ARIALBD.ttf') format('truetype');
}
@font-face {
font-family: 'ArialMedium';
src: url('./ArialMdm.ttf') format('truetype');
}
@font-face {
font-family: 'Poppins';
src: url('./Poppins-Regular.ttf') format('truetype');
font-weight: normal;
}
@font-face {
font-family: 'PoppinsMedium';
src: url('./Poppins-Medium.ttf') format('truetype');
}
@font-face {
font-family: 'PoppinsBold';
src: url('./Poppins-SemiBold.ttf') format('truetype');
}
@font-face {
font-family: 'Instrument';
src: url('./InstrumentSans-Regular.ttf') format('truetype');
}
@font-face {
font-family: 'InstrumentBold';
src: url('./InstrumentSans-Bold.ttf') format('truetype');
}

View File

@@ -7,6 +7,7 @@ import 'normalize.css'
import './assets/css/style.css'
import SvgIcon from "@/components/SvgIcon/index.vue";
import "virtual:svg-icons-register";
// import './assets/css/fonts/fontFamily.css'
import i18n from "./lang/index";

View File

@@ -1,32 +1,87 @@
import { getUniversalZoomLevel } from '@/utils/tools'
import { getUniversalZoomLevel } from '@/utils/util'
import MyEvent from '@/utils/myEvent'
const maxWidth = 1920;
const minWidth = 500;
let flexible = (designWidth = 1920) => {
var doc = document, win = window, docEl = doc.documentElement, remStyle = document.createElement("style"), tid;
function refreshRem() {
var width = docEl.getBoundingClientRect().width;
var height = docEl.getBoundingClientRect().height;
width = getUniversalZoomLevel() * width
height = getUniversalZoomLevel() * height
if (width > maxWidth) width = maxWidth;
if (width < minWidth) width = minWidth;
var rem = (width * 10 / designWidth).toFixed(2);
docEl.style.fontSize = rem + 'px'
}
//要等 wiewport 设置好后才能执行 refreshRem不然 refreshRem 会执行2次
refreshRem();
win.addEventListener("resize", function () {
clearTimeout(tid); //防止执行两次
tid = setTimeout(refreshRem, 200);
}, false);
let flexible = (designWidth, maxWidth, minWidth) => {
var doc = document,
win = window,
docEl = doc.documentElement,
remStyle = document.createElement('style'),
tid
designWidth = designWidth || 1920
maxWidth = maxWidth || 2560
minWidth = minWidth || 1024
let oldDesignWidth = designWidth
win.addEventListener("pageshow", function (e) {
if (e.persisted) { // 浏览器后退的时候重新计算
clearTimeout(tid);
tid = setTimeout(refreshRem, 200);
}
}, false);
};
// minWidth = minWidth || 1024;
function refreshRem() {
var width = docEl.getBoundingClientRect().width
var height = docEl.getBoundingClientRect().height
width = getUniversalZoomLevel() * width
height = getUniversalZoomLevel() * height
maxWidth = maxWidth || 1920
if (width < 1100) {
document.body.classList.add('ipad')
} else {
document.body.classList.remove('ipad')
}
if (width > 768) {
if (width / height > 1.98) width = height * 1.98
width > maxWidth && (width = maxWidth)
width < minWidth && (width = minWidth)
designWidth = oldDesignWidth
} else {
designWidth = 393
}
console.log(width, designWidth)
export default flexible
// var rem = width * 10 / designWidth;
var rem = Math.round((width * 10) / designWidth)
docEl.style.fontSize = rem + 'px'
remStyle.innerHTML = 'html{font-size:' + rem + 'px;}'
MyEvent.emit('remChange', rem)
}
// if (docEl.firstElementChild) {
// docEl.firstElementChild.appendChild(remStyle);
// } else {
// var wrap = doc.createElement("div");
// wrap.appendChild(remStyle);
// doc.write(wrap.innerHTML);
// wrap = null;
// }
//要等 wiewport 设置好后才能执行 refreshRem不然 refreshRem 会执行2次
refreshRem()
win.addEventListener(
'resize',
function () {
clearTimeout(tid) //防止执行两次
tid = setTimeout(refreshRem, 300)
},
false
)
win.addEventListener(
'pageshow',
function (e) {
if (e.persisted) {
// 浏览器后退的时候重新计算
clearTimeout(tid)
tid = setTimeout(refreshRem, 300)
}
},
false
)
if (doc.readyState === 'complete') {
doc.body.style.fontSize = '16px'
} else {
doc.addEventListener(
'DOMContentLoaded',
function (e) {
doc.body.style.fontSize = '16px'
},
false
)
}
}
export default flexible

703
src/utils/util.ts Normal file
View File

@@ -0,0 +1,703 @@
const isEmail = (email) => {
// let reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,})$/
let reg = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
let result = reg.test(email)
return result
}
function getUniversalZoomLevel() {
// 现代浏览器方案
if (window.visualViewport) {
return window.visualViewport.scale
}
// 备用方案1
if (window.devicePixelRatio) {
return window.devicePixelRatio
}
// 备用方案2不精确
return window.outerWidth / window.innerWidth
}
const getUploadUrl = () => {
let url = import.meta.env.VITE_APP_BASE_URL || ''
// let url = "http://18.167.251.121:10086"
return url
}
const getMinioUrl = (url) => {
if (!isValidMinioUrl(url)) return ''
if (isUrl(url)) {
const { pathname } = new URL(url)
const result = pathname.slice(1)
return result
}
return ''
}
function isValidMinioUrl(url) {
return url.includes('www.minio-api.aida.com.hk') // 关键特征检测
}
function isUrl(str) {
try {
new URL(str)
return true
} catch (e) {
return false
}
}
const rgbaToHex = (rgba) => {
// rgba转16进制
let hex = '#'
rgba.forEach((i, index) => {
if (index == 3) {
hex += Math.round(i * 255).toString(16)
} else {
hex += Number(i).toString(16).padStart(2, '0')
}
})
return hex
}
function base64ToFile(urlData, name) {
let arr = urlData.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], name, {
type: mime
})
}
function dataURLtoBlob(dataurl) {
//吧data url转为blob对象
var arr = dataurl.split(',')
var mime = arr[0].match(/:(.*?);/)[1]
var bstr = atob(arr[1])
var n = bstr.length
var u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: mime })
}
function blobToFile(blob, fileName) {
//给blob文件设置名字和日期
blob.lastModifiedDate = new Date()
blob.name = fileName
return blob
}
//下载图片
function downloadIamge(imgsrc, name) {
// 下载图片地址和图片名
var image = new Image()
// 解决跨域 Canvas 污染问题
image.setAttribute('crossOrigin', 'anonymous')
image.onload = function () {
var canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
var context = canvas.getContext('2d')
context.drawImage(image, 0, 0, image.width, image.height)
var url = canvas.toDataURL('image/png') // 得到图片的base64编码数据
var a = document.createElement('a') // 生成一个a元素
var event = new MouseEvent('click') // 创建一个单击事件
a.download = name || 'generate' // 设置图片名称
a.href = url // 将生成的URL设置为a.href属性
a.target = '_blank'
a.dispatchEvent(event) // 触发a的单击事件
image.remove()
}
image.src = imgsrc
}
async function downloadVideoWithFetch(url, filename) {
try {
const response = await fetch(url)
const blob = await response.blob()
const blobUrl = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = blobUrl
a.download = filename || 'video.mp4'
document.body.appendChild(a)
a.click()
// 清理
setTimeout(() => {
document.body.removeChild(a)
URL.revokeObjectURL(blobUrl)
}, 100)
} catch (error) {
console.error('下载失败:', error)
}
}
function dataURLtoFile(dataurl, filename) {
//吧url转为文件对象指定文件名称
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
var blob = dataURLtoBlob(dataurl)
return blobToFile(blob, filename)
}
const base64toFile = (dataurl, filename = 'file') => {
//转换base64
let arr = dataurl.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let suffix = mime.split('/')[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], `${filename}.${suffix}`, {
type: mime
})
}
const UrlToFile = async (url, imageName) => {
const response = await fetch(url)
const blob = await response.blob()
return new File([blob], imageName, { type: 'image/png' })
}
function rgbToHsv([R, G, B]) {
//根据rgb获取hsv
R /= 255
G /= 255
B /= 255
const max = Math.max(R, G, B)
const min = Math.min(R, G, B)
const delta = max - min
var H, S, V
if (delta === 0) {
H = 0
} else if (max === R) {
H = ((G - B) / delta) % 6
} else if (max === G) {
H = (B - R) / delta + 2
} else {
// max === B
H = (R - G) / delta + 4
}
H = Math.round(H * 60) // 范围为 0-360
if (H < 0) {
H = 360 + H
}
if (max === 0) {
S = 0
} else {
S = delta / max
}
S = Math.round(S * 100) // 范围为 0-100
V = Math.round(max * 100) // 范围为 0-100
return [H, S, V]
}
const formatTime = (timestamp, fmt) => {
//吧时间戳转为YYYY-MM-DD hh:mm:ss格式
// date = new Date(), fmt = 'MM/dd/yyyy';
let date = new Date()
date.setTime(timestamp * 1000)
if (!fmt) {
formatRule ? (fmt = formatRule) : (fmt = 'YYYY-MM-DD hh:mm:ss')
}
// console.log(formatRule)
let o = {
'M+': date.getMonth() + 1, // 月份
'D+': date.getDate(), // 日
'h+': date.getHours(), // 小时
'm+': date.getMinutes(), // 分
's+': date.getSeconds(), // 秒
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
'S+': date.getMilliseconds(), // 毫秒
a: date.getHours() > 12 ? 'PM' : 'AM' // 上午还是下午
}
if (/(Y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
}
if (/(a)/.test(fmt) && o['h+'] > 12) {
o['h+'] = o['h+'] - 12
}
for (let k in o) {
if (new RegExp('(' + k + ')').test(fmt)) {
fmt = fmt.replace(
RegExp.$1,
RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
)
}
}
return fmt
}
const isMoible = () => {
//判断是否是移动端
let is_mobile =
navigator.userAgent
.toLowerCase()
.match(
/(ipad|ipod|iphone|android|coolpad|mmp|smartphone|midp|wap|xoom|symbian|j2me|blackberry|wince)/i
) != null
// alert(navigator.userAgent.toLowerCase())
var isiPad = navigator.maxTouchPoints && navigator.maxTouchPoints > 1
// if (is_mobile) {
// return true//判断是否在正则内
// } else if(window.matchMedia("(pointer:fine)").matches){
// return false//判断是否支持鼠标
// }else{
// isiPad//判断触摸点
// }
if (is_mobile) {
return true //判断是否在正则内
} else {
return isiPad //判断触摸点
}
}
let setPubDate = (date, t) => {
const timestamp = new Date(date)
const now = new Date()
// 计算时间差(以毫秒为单位)
const differenceMs = now - timestamp
const seconds = Math.floor(differenceMs / 1000)
const minutes = Math.floor(seconds / 60)
const hours = Math.floor(minutes / 60)
const days = Math.floor(hours / 24)
const weeks = Math.floor(days / 7)
const months = Math.floor(days / 30)
const years = Math.floor(days / 365)
// 根据时间差的大小返回不同的描述
if (years > 0) {
return `${years} ${t('newScaleImage.yearsAgo')}`
} else if (months > 0) {
return `${months} ${t('newScaleImage.monthsAgo')}`
} else if (weeks > 0) {
return `${weeks} ${t('newScaleImage.WeeksAgo')}`
} else if (days > 0) {
return `${t('newScaleImage.daysAgo')}`
} else if (hours > 0) {
return `${hours} ${t('newScaleImage.HoursAgo')}`
} else if (minutes > 0) {
return `${minutes} ${t('newScaleImage.minutesAgo')}`
} else {
return `${t('newScaleImage.minuteAgo')}`
}
}
function getBrowserInfo() {
//获取是什么浏览器
var agent = navigator.userAgent.toLowerCase()
var userAgent = navigator.userAgent
var regStr_ie = /msie [\d.]+;/gi
var regStr_ff = /firefox\/[\d.]+/gi
var regStr_chrome = /chrome\/[\d.]+/gi
var regStr_saf = /safari\/[\d.]+/gi
var isIE = userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1 //判断是否IE<11浏览器
var isEdge = userAgent.indexOf('Edge') > -1 && !isIE //判断是否IE的Edge浏览器
//IE
if (agent.indexOf('msie') > 0) {
return agent.match(regStr_ie)
}
//firefox
if (agent.indexOf('firefox') > 0) {
return agent.match(regStr_ff)
}
//Chrome
if (agent.indexOf('chrome') > 0) {
return agent.match(regStr_chrome)
}
//Safari
if (agent.indexOf('safari') > 0 && agent.indexOf('chrome') < 0) {
return agent.match(regStr_saf)
}
}
async function murmur() {
//生成唯一标识 ,暂时没有使用
return await new Promise((resolve, reject) => {
Fingerprint2.get(function (components) {
const values = components.map(function (component, index) {
if (index === 0) {
//把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样
return component.value.replace(/\bNetType\/\w+\b/, '')
}
return component.value
})
// 生成最终id murmur
let murmur = Fingerprint2.x64hash128(values.join(''), 31)
resolve(murmur)
})
})
}
/**
* @description: 计算canvas渐变起始坐标
* @param {number} canvas width
* @param {number} canvas height
* @param {number} angle 角度
* @return {*}
*/
function calculateGradientCoordinate(width, height, angle) {
if (angle >= 360) angle = angle - 360
if (angle < 0) angle = angle + 360
angle = Math.round(angle)
// 当渐变轴垂直于矩形水平边上的两种结果
if (angle === 0) {
return {
x0: Math.round(width / 2),
y0: height,
x1: Math.round(width / 2),
y1: 0
}
}
if (angle === 180) {
return {
x0: Math.round(width / 2),
y0: 0,
x1: Math.round(width / 2),
y1: height
}
}
// 当渐变轴垂直于矩形垂直边上的两种结果
if (angle === 90) {
return {
x0: 0,
y0: Math.round(height / 2),
x1: width,
y1: Math.round(height / 2)
}
}
if (angle === 270) {
return {
x0: width,
y0: Math.round(height / 2),
x1: 0,
y1: Math.round(height / 2)
}
}
// 从矩形左下角至右上角的对角线的角度
const alpha = Math.round(
(Math.asin(width / Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2))) * 180) / Math.PI
)
// 当渐变轴分别于矩形的两条对角线重合情况下的四种结果
if (angle === alpha) {
return {
x0: 0,
y0: height,
x1: width,
y1: 0
}
}
if (angle === 180 - alpha) {
return {
x0: 0,
y0: 0,
x1: width,
y1: height
}
}
if (angle === 180 + alpha) {
return {
x0: width,
y0: 0,
x1: 0,
y1: height
}
}
if (angle === 360 - alpha) {
return {
x0: width,
y0: height,
x1: 0,
y1: 0
}
}
// 以矩形的中点为坐标原点向上为Y轴正方向向右为X轴正方向建立直角坐标系
let x0 = 0,
y0 = 0,
x1 = 0,
y1 = 0
// 当渐变轴与矩形的交点落在水平线上
if (
angle < alpha || // 处于第一象限
(angle > 180 - alpha && angle < 180) || // 处于第二象限
(angle > 180 && angle < 180 + alpha) || // 处于第三象限
angle > 360 - alpha // 处于第四象限
) {
// 将角度乘以PI/180即可转换为弧度
const radian = (angle * Math.PI) / 180
// 当在第一或第四象限y是height / 2否则y是-height / 2
const y = angle < alpha || angle > 360 - alpha ? height / 2 : -height / 2
const x = Math.tan(radian) * y
// 当在第一或第二象限l是width / 2 - x否则l是-width / 2 - x
const l = angle < alpha || (angle > 180 - alpha && angle < 180) ? width / 2 - x : -width / 2 - x
const n = Math.pow(Math.sin(radian), 2) * l
x1 = x + n
y1 = y + n / Math.tan(radian)
x0 = -x1
y0 = -y1
}
// 当渐变轴与矩形的交点落在垂直线上
if (
(angle > alpha && angle < 90) || // 处于第一象限
(angle > 90 && angle < 180 - alpha) || // 处于第二象限
(angle > 180 + alpha && angle < 270) || // 处于第三象限
(angle > 270 && angle < 360 - alpha) // 处于第四象限
) {
// 将角度乘以PI/180即可转换为弧度
const radian = ((90 - angle) * Math.PI) / 180
// 当在第一或第二象限x是width / 2否则x是-width / 2
const x =
(angle > alpha && angle < 90) || (angle > 90 && angle < 180 - alpha) ? width / 2 : -width / 2
const y = Math.tan(radian) * x
// 当在第一或第四象限l是height / 2 - y否则l是-height / 2 - y
const l =
(angle > alpha && angle < 90) || (angle > 270 && angle < 360 - alpha)
? height / 2 - y
: -height / 2 - y
const n = Math.pow(Math.sin(radian), 2) * l
x1 = x + n / Math.tan(radian)
y1 = y + n
x0 = -x1
y0 = -y1
}
// 坐标系更改为canvas标准Y轴向下为正方向
x0 = Math.round(x0 + width / 2)
y0 = Math.round(height / 2 - y0)
x1 = Math.round(x1 + width / 2)
y1 = Math.round(height / 2 - y1)
return { x0, y0, x1, y1 }
}
const setGradual = (colorObj, colorWidth, colorHeight) => {
return new Promise((resolve, reject) => {
let width = colorWidth || 320
let height = colorHeight || 700
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = width
canvas.height = height
let { x0, y0, x1, y1 } = calculateGradientCoordinate(width, height, colorObj.angle)
const gradient = ctx.createLinearGradient(x0, y0, x1, y1)
colorObj.gradientList.forEach((item) => {
let left = item.left.split('%')[0] / 100
let rgba = `rgba(${item.rgba.r},${item.rgba.g},${item.rgba.b},${item.rgba.a})`
gradient.addColorStop(left, rgba) // 起始颜色
})
ctx.fillStyle = gradient
ctx.fillRect(0, 0, width, height)
// let dataURL = canvas.toDataURL('image/jpg');
resolve(canvas.toDataURL('image/jpg'))
})
}
function segmentImage(markerImage, fullImage, size) {
return new Promise((resolve, reject) => {
const markerCanvas = document.createElement('canvas')
const fullCanvas = document.createElement('canvas')
const nullCanvas = document.createElement('canvas')
const ctx1 = markerCanvas.getContext('2d')
const ctx2 = fullCanvas.getContext('2d')
const ctx3 = nullCanvas.getContext('2d')
markerCanvas.width = size.width
markerCanvas.height = size.height
fullCanvas.height = size.height
fullCanvas.width = size.width
nullCanvas.height = size.height
nullCanvas.width = size.width
let targetFrontUrl = ''
let targetBackUrl = ''
const marker = new Image()
const full = new Image()
marker.crossOrigin = 'anonymous'
full.crossOrigin = 'anonymous'
marker.onload = () => {
ctx1.drawImage(marker, 0, 0, size.width, size.height)
full.onload = () => {
ctx2.drawImage(full, 0, 0, size.width, size.height)
segmentImageItem()
}
full.src = fullImage
}
marker.src = markerImage
function segmentImageItem() {
const markerData = ctx1.getImageData(0, 0, size.width, size.height)
const fullData = ctx2.getImageData(0, 0, size.width, size.height)
const color1 = { r: 255, g: 0, b: 0 } // 第一个颜色
const color2 = { r: 0, g: 255, b: 0 } // 第二个颜色
const threshold = 100 // 颜色匹配的容差
// const isColorMatch = (r, g, b, color) =>
// (Math.abs(r - color.r) < threshold) || (Math.abs(0 - color.r) < threshold) &&
// (Math.abs(g - color.g) < threshold) || (Math.abs(0 - color.g) < threshold) &&
// (Math.abs(b - color.b) < threshold) || (Math.abs(0 - color.b) < threshold)
const isColorMatch = (r, g, b, color) =>
(color.r >= color.g && r >= g) || (color.r < color.g && r < g)
// (Math.abs(b - color.b) < threshold || Math.abs(0 - color.b) < threshold)
const output1 = ctx3.createImageData(size.width, size.height)
const output2 = ctx3.createImageData(size.width, size.height)
for (let i = 0; i < markerData.data.length; i += 4) {
const r = markerData.data[i]
const g = markerData.data[i + 1]
const b = markerData.data[i + 2]
let a = markerData.data[i + 3]
a > 1 ? (a = 255) : 0
if (r >= g && a > 1) {
// 将完整图像中对应的像素复制到第一个输出图像
output1.data[i] = fullData.data[i]
output1.data[i + 1] = fullData.data[i + 1]
output1.data[i + 2] = fullData.data[i + 2]
output1.data[i + 3] = fullData.data[i + 3]
// output1.data[i] = 158;
// output1.data[i + 1] = 51;
// output1.data[i + 2] = 0;
// output1.data[i + 3] = 255;
// 第二个图像的像素置为透明
output2.data[i] = 0
output2.data[i + 1] = 0
output2.data[i + 2] = 0
output2.data[i + 3] = 0
} else if (r < g && a > 1) {
// 将完整图像中对应的像素复制到第二个输出图像
output2.data[i] = fullData.data[i]
output2.data[i + 1] = fullData.data[i + 1]
output2.data[i + 2] = fullData.data[i + 2]
output2.data[i + 3] = fullData.data[i + 3]
// output2.data[i] = 158;
// output2.data[i + 1] = 51;
// output2.data[i + 2] = 0;
// output2.data[i + 3] = 255;
// 第一个图像的像素置为透明
output1.data[i] = 0
output1.data[i + 1] = 0
output1.data[i + 2] = 0
output1.data[i + 3] = 0
} else {
// 两个图像的像素都置为透明
output1.data[i] = 0
output1.data[i + 1] = 0
output1.data[i + 2] = 0
output1.data[i + 3] = 0
output2.data[i] = 0
output2.data[i + 1] = 0
output2.data[i + 2] = 0
output2.data[i + 3] = 0
}
}
const createImageURL = (imageData) => {
const canvas = document.createElement('canvas')
canvas.width = size.width
canvas.height = size.height
const ctx = canvas.getContext('2d')
ctx.putImageData(imageData, 0, 0)
let data = canvas.toDataURL('image/png')
canvas.remove()
return data
}
targetBackUrl = createImageURL(output2)
targetFrontUrl = createImageURL(output1)
resolve({ targetFrontUrl, targetBackUrl })
markerCanvas.remove()
fullCanvas.remove()
nullCanvas.remove()
}
})
}
/**
* 处理PNG图片透明度转白色其他颜色转透明
* @param {string} sketchImage - 原始图片
* @returns {Promise} 处理后的ase64
*/
function sketchToMask(sketchImage) {
return new Promise((resolve, reject) => {
const img = new Image()
img.crossOrigin = 'anonymous'
img.onload = function () {
try {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = img.width
canvas.height = img.height
ctx.drawImage(img, 0, 0)
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
const data = imageData.data
for (let i = 0; i < data.length; i += 4) {
const r = data[i]
const g = data[i + 1]
const b = data[i + 2]
const a = data[i + 3]
if (a > 0) {
data[i] = 0
data[i + 1] = 0
data[i + 2] = 0
data[i + 3] = 0
} else {
// 完全透明的像素 -> 纯白色
data[i] = 255
data[i + 1] = 255
data[i + 2] = 255
data[i + 3] = 255
}
}
ctx.putImageData(imageData, 0, 0)
const base64 = canvas.toDataURL('image/png')
resolve(base64)
} catch (error) {
reject(error)
}
}
img.onerror = function () {
reject(new Error('图片加载失败'))
}
img.src = sketchImage
})
}
export {
isEmail,
getUploadUrl,
getUniversalZoomLevel,
rgbaToHex,
getMinioUrl,
base64ToFile,
dataURLtoFile,
blobToFile,
base64toFile,
rgbToHsv,
formatTime,
dataURLtoBlob,
isMoible,
downloadIamge,
downloadVideoWithFetch,
getBrowserInfo,
setPubDate,
murmur,
setGradual,
calculateGradientCoordinate,
segmentImage,
UrlToFile,
sketchToMask
}