画布高清处理
This commit is contained in:
14
cool/utils/device.ts
Normal file
14
cool/utils/device.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* 获取设备像素比
|
||||||
|
* @returns 设备像素比
|
||||||
|
*/
|
||||||
|
export const getDevicePixelRatio = (): number => {
|
||||||
|
const dpr = uni.getDeviceInfo().devicePixelRatio ?? 1;
|
||||||
|
|
||||||
|
// #ifdef MP
|
||||||
|
// 微信小程序高清处理
|
||||||
|
return 3;
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
return dpr;
|
||||||
|
};
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
export * from "./comm";
|
export * from "./comm";
|
||||||
export * from "./storage";
|
|
||||||
export * from "./path";
|
|
||||||
export * from "./day";
|
export * from "./day";
|
||||||
export * from "./parse";
|
export * from "./device";
|
||||||
export * from "./file";
|
export * from "./file";
|
||||||
|
export * from "./parse";
|
||||||
|
export * from "./path";
|
||||||
|
export * from "./storage";
|
||||||
|
|||||||
@@ -132,7 +132,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, reactive, nextTick, getCurrentInstance } from "vue";
|
import { computed, ref, reactive, nextTick, getCurrentInstance } from "vue";
|
||||||
import type { PassThroughProps } from "../../types";
|
import type { PassThroughProps } from "../../types";
|
||||||
import { canvasToPng, parsePt, usePage, uuid } from "@/cool";
|
import { canvasToPng, getDevicePixelRatio, parsePt, usePage, uuid } from "@/cool";
|
||||||
|
|
||||||
// 定义遮罩层样式类型
|
// 定义遮罩层样式类型
|
||||||
type MaskStyle = {
|
type MaskStyle = {
|
||||||
@@ -1085,24 +1085,25 @@ async function toPng(): Promise<string> {
|
|||||||
id: canvasId,
|
id: canvasId,
|
||||||
component: proxy,
|
component: proxy,
|
||||||
success: (context: CanvasContext) => {
|
success: (context: CanvasContext) => {
|
||||||
|
// 获取设备像素比
|
||||||
|
const dpr = getDevicePixelRatio();
|
||||||
|
|
||||||
// 获取绘图上下文
|
// 获取绘图上下文
|
||||||
const ctx = context.getContext("2d")!;
|
const ctx = context.getContext("2d")!;
|
||||||
|
|
||||||
|
// 设置宽高
|
||||||
|
ctx!.canvas.width = cropBox.width * dpr;
|
||||||
|
ctx!.canvas.height = cropBox.height * dpr;
|
||||||
|
|
||||||
// #ifdef APP
|
// #ifdef APP
|
||||||
ctx!.reset();
|
ctx!.reset();
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifndef APP
|
// #ifndef APP
|
||||||
ctx!.clearRect(0, 0, cropBox.width, cropBox.height);
|
ctx!.clearRect(0, 0, cropBox.width * dpr, cropBox.height * dpr);
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// 获取设备像素比
|
// 创建图片
|
||||||
const dpr = uni.getDeviceInfo().devicePixelRatio ?? 1;
|
|
||||||
|
|
||||||
// 设置宽高
|
|
||||||
ctx!.canvas.width = cropBox.width * dpr;
|
|
||||||
ctx!.canvas.height = cropBox.height * dpr;
|
|
||||||
|
|
||||||
let img: Image;
|
let img: Image;
|
||||||
|
|
||||||
// 微信小程序环境创建图片
|
// 微信小程序环境创建图片
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { getColor, isDark, parseClass, parsePt, uuid } from "@/cool";
|
import { getColor, getDevicePixelRatio, isDark, parseClass, parsePt, uuid } from "@/cool";
|
||||||
import { computed, getCurrentInstance, onMounted, ref, watch, type PropType } from "vue";
|
import { computed, getCurrentInstance, onMounted, ref, watch, type PropType } from "vue";
|
||||||
import type { PassThroughProps } from "../../types";
|
import type { PassThroughProps } from "../../types";
|
||||||
|
|
||||||
@@ -89,6 +89,9 @@ const props = defineProps({
|
|||||||
|
|
||||||
const { proxy } = getCurrentInstance()!;
|
const { proxy } = getCurrentInstance()!;
|
||||||
|
|
||||||
|
// 获取设备像素比
|
||||||
|
const dpr = getDevicePixelRatio();
|
||||||
|
|
||||||
// 透传样式类型定义
|
// 透传样式类型定义
|
||||||
type PassThrough = {
|
type PassThrough = {
|
||||||
className?: string;
|
className?: string;
|
||||||
@@ -114,25 +117,22 @@ const value = ref(0);
|
|||||||
function drawProgress() {
|
function drawProgress() {
|
||||||
if (drawCtx == null) return;
|
if (drawCtx == null) return;
|
||||||
|
|
||||||
const centerX = props.size / 2;
|
const centerX = (props.size / 2) * dpr;
|
||||||
const centerY = props.size / 2;
|
const centerY = (props.size / 2) * dpr;
|
||||||
const radius = (props.size - props.strokeWidth) / 2;
|
const radius = ((props.size - props.strokeWidth) / 2) * dpr;
|
||||||
|
|
||||||
// 清除画布
|
// 清除画布
|
||||||
// #ifdef APP
|
// #ifdef APP
|
||||||
drawCtx!.reset();
|
drawCtx!.reset();
|
||||||
// #endif
|
// #endif
|
||||||
// #ifndef APP
|
// #ifndef APP
|
||||||
drawCtx!.clearRect(0, 0, props.size, props.size);
|
drawCtx!.clearRect(0, 0, props.size * dpr, props.size * dpr);
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// 获取设备像素比
|
// 优化渲染质量
|
||||||
const dpr = uni.getDeviceInfo().devicePixelRatio ?? 1;
|
drawCtx!.textBaseline = "middle";
|
||||||
|
drawCtx!.textAlign = "center";
|
||||||
// #ifndef H5
|
drawCtx!.miterLimit = 10;
|
||||||
// 设置缩放比例
|
|
||||||
drawCtx!.scale(dpr, dpr);
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// 保存当前状态
|
// 保存当前状态
|
||||||
drawCtx!.save();
|
drawCtx!.save();
|
||||||
@@ -143,7 +143,7 @@ function drawProgress() {
|
|||||||
drawCtx!.beginPath();
|
drawCtx!.beginPath();
|
||||||
drawCtx!.arc(centerX, centerY, radius, startAngle, endAngle, false);
|
drawCtx!.arc(centerX, centerY, radius, startAngle, endAngle, false);
|
||||||
drawCtx!.strokeStyle = color;
|
drawCtx!.strokeStyle = color;
|
||||||
drawCtx!.lineWidth = props.strokeWidth;
|
drawCtx!.lineWidth = props.strokeWidth * dpr;
|
||||||
drawCtx!.lineCap = "round";
|
drawCtx!.lineCap = "round";
|
||||||
drawCtx!.lineJoin = "round";
|
drawCtx!.lineJoin = "round";
|
||||||
drawCtx!.stroke();
|
drawCtx!.stroke();
|
||||||
@@ -214,13 +214,8 @@ function initCanvas() {
|
|||||||
drawCtx = context.getContext("2d")!;
|
drawCtx = context.getContext("2d")!;
|
||||||
|
|
||||||
// 设置宽高
|
// 设置宽高
|
||||||
drawCtx!.canvas.width = props.size;
|
drawCtx!.canvas.width = props.size * dpr;
|
||||||
drawCtx!.canvas.height = props.size;
|
drawCtx!.canvas.height = props.size * dpr;
|
||||||
|
|
||||||
// 优化渲染质量
|
|
||||||
drawCtx!.textBaseline = "middle";
|
|
||||||
drawCtx!.textAlign = "center";
|
|
||||||
drawCtx!.miterLimit = 10;
|
|
||||||
|
|
||||||
// 开始动画
|
// 开始动画
|
||||||
animate(props.value);
|
animate(props.value);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { canvasToPng, parsePt, uuid } from "@/cool";
|
import { canvasToPng, getDevicePixelRatio, parsePt, uuid } from "@/cool";
|
||||||
import { computed, getCurrentInstance, nextTick, onMounted, ref, shallowRef, watch } from "vue";
|
import { computed, getCurrentInstance, nextTick, onMounted, ref, shallowRef, watch } from "vue";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@@ -77,11 +77,14 @@ const props = defineProps({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 定义事件发射器
|
// 定义事件发射器
|
||||||
const emit = defineEmits(["change"]);
|
const emit = defineEmits(["change", "clear"]);
|
||||||
|
|
||||||
// 获取当前实例
|
// 获取当前实例
|
||||||
const { proxy } = getCurrentInstance()!;
|
const { proxy } = getCurrentInstance()!;
|
||||||
|
|
||||||
|
// 获取设备像素比
|
||||||
|
const dpr = getDevicePixelRatio();
|
||||||
|
|
||||||
// 触摸点类型
|
// 触摸点类型
|
||||||
type Point = { x: number; y: number; time: number };
|
type Point = { x: number; y: number; time: number };
|
||||||
|
|
||||||
@@ -241,10 +244,10 @@ function onTouchMove(e: TouchEvent) {
|
|||||||
|
|
||||||
// 绘制线条
|
// 绘制线条
|
||||||
drawCtx!.beginPath();
|
drawCtx!.beginPath();
|
||||||
drawCtx!.moveTo(lastPoint!.x, lastPoint!.y);
|
drawCtx!.moveTo(lastPoint!.x * dpr, lastPoint!.y * dpr);
|
||||||
drawCtx!.lineTo(currentPoint.x, currentPoint.y);
|
drawCtx!.lineTo(currentPoint.x * dpr, currentPoint.y * dpr);
|
||||||
drawCtx!.strokeStyle = props.strokeColor;
|
drawCtx!.strokeStyle = props.strokeColor;
|
||||||
drawCtx!.lineWidth = strokeWidth;
|
drawCtx!.lineWidth = strokeWidth * dpr;
|
||||||
drawCtx!.lineCap = "round";
|
drawCtx!.lineCap = "round";
|
||||||
drawCtx!.lineJoin = "round";
|
drawCtx!.lineJoin = "round";
|
||||||
drawCtx!.stroke();
|
drawCtx!.stroke();
|
||||||
@@ -269,22 +272,14 @@ function clear() {
|
|||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifndef APP
|
// #ifndef APP
|
||||||
drawCtx!.clearRect(0, 0, props.width, props.height);
|
drawCtx!.clearRect(0, 0, props.width * dpr, props.height * dpr);
|
||||||
// #endif
|
|
||||||
|
|
||||||
// 获取设备像素比
|
|
||||||
const dpr = uni.getDeviceInfo().devicePixelRatio ?? 1;
|
|
||||||
|
|
||||||
// #ifndef H5
|
|
||||||
// 设置缩放比例
|
|
||||||
drawCtx!.scale(dpr, dpr);
|
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// 填充背景色
|
// 填充背景色
|
||||||
drawCtx!.fillStyle = props.backgroundColor;
|
drawCtx!.fillStyle = props.backgroundColor;
|
||||||
drawCtx!.fillRect(0, 0, props.width, props.height);
|
drawCtx!.fillRect(0, 0, props.width * dpr, props.height * dpr);
|
||||||
|
|
||||||
emit("change");
|
emit("clear");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取签名图片
|
// 获取签名图片
|
||||||
@@ -300,10 +295,9 @@ function initCanvas() {
|
|||||||
success: (context: CanvasContext) => {
|
success: (context: CanvasContext) => {
|
||||||
// 获取绘图上下文
|
// 获取绘图上下文
|
||||||
drawCtx = context.getContext("2d")!;
|
drawCtx = context.getContext("2d")!;
|
||||||
|
|
||||||
// 设置宽高
|
// 设置宽高
|
||||||
drawCtx!.canvas.width = props.width;
|
drawCtx!.canvas.width = props.width * dpr;
|
||||||
drawCtx!.canvas.height = props.height;
|
drawCtx!.canvas.height = props.height * dpr;
|
||||||
|
|
||||||
// 优化渲染质量
|
// 优化渲染质量
|
||||||
drawCtx!.textBaseline = "middle";
|
drawCtx!.textBaseline = "middle";
|
||||||
|
|||||||
Reference in New Issue
Block a user