细节优化
This commit is contained in:
@@ -481,3 +481,64 @@ async function loadCanvasImage(canvas, src) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export const sharePractiseData = async (canvasId, data) => {
|
||||
try {
|
||||
const width = 375;
|
||||
const height = 460;
|
||||
// 获取 Canvas 2D 上下文并按 DPR 设置
|
||||
const { canvas, ctx } = await getCanvas2DContext(canvasId, width, height);
|
||||
|
||||
// 背景填充
|
||||
ctx.fillStyle = "#F5F5F5";
|
||||
ctx.fillRect(0, 0, width, height);
|
||||
|
||||
// 背景图
|
||||
const bgSrc = await loadImage(
|
||||
"https://static.shelingxingqiu.com/attachment/2026-01-05/dfgirwfuz5htwfd4sd.png"
|
||||
);
|
||||
const bgImg = await loadCanvasImage(canvas, bgSrc);
|
||||
ctx.drawImage(bgImg, 0, 0, width, width);
|
||||
|
||||
// 头像
|
||||
const avatarSrc = await loadImage(data.avatar);
|
||||
const avatarImg = await loadCanvasImage(canvas, avatarSrc);
|
||||
await drawRoundImage(ctx, avatarImg, 13, 13, 54, 54, 27, "#fff", 1);
|
||||
|
||||
renderText(ctx, data.name, 20, "#fff", 84, 50);
|
||||
|
||||
const bubble1Src = await loadImage(
|
||||
"https://static.shelingxingqiu.com/attachment/2026-01-05/dfgirwcxugdsenlnud.png"
|
||||
);
|
||||
const bubble2Src = await loadImage(
|
||||
"https://static.shelingxingqiu.com/attachment/2026-01-05/dfgirwcxujhysg0vfq.png"
|
||||
);
|
||||
const bubble3Src = await loadImage(
|
||||
"https://static.shelingxingqiu.com/attachment/2026-01-05/dfgirwfa33spdori3p.png"
|
||||
);
|
||||
const bubble1Img = await loadCanvasImage(canvas, bubble1Src);
|
||||
const bubble2Img = await loadCanvasImage(canvas, bubble2Src);
|
||||
const bubble3Img = await loadCanvasImage(canvas, bubble3Src);
|
||||
ctx.drawImage(bubble1Img, 10, 88, 143, 87);
|
||||
renderText(ctx, "本周箭数", 14, "#FDA103", 84, 116, "center");
|
||||
renderText(ctx, data.weekArrow, 36, "#FA2A2A", 84, 152, "center");
|
||||
ctx.drawImage(bubble2Img, 65, 220, 143, 87);
|
||||
renderText(ctx, "本周消耗", 14, "#FDA103", 139, 248, "center");
|
||||
renderText(ctx, data.weekArrow * 1.6, 36, "#FA2A2A", 139, 284, "center");
|
||||
ctx.drawImage(bubble3Img, 255, 52, 114, 92);
|
||||
renderText(ctx, "我的名次", 14, "#FDA103", 312, 80, "center");
|
||||
renderText(ctx, data.rank, 36, "#FA2A2A", 312, 116, "center");
|
||||
|
||||
const qrcodeSrc = await loadImage(
|
||||
"https://static.shelingxingqiu.com/attachment/2025-12-04/dep7lfqhpelmerjle4.png"
|
||||
);
|
||||
const qrcodeImg = await loadCanvasImage(canvas, qrcodeSrc);
|
||||
ctx.drawImage(qrcodeImg, 40, 383, 68, 68);
|
||||
|
||||
renderText(ctx, "射灵星球", 18, "#333", 120, 412);
|
||||
renderText(ctx, "高效记录每一箭,快来一起打卡吧!", 13, "#999", 120, 435);
|
||||
// 2D 即时绘制,无需 ctx.draw()
|
||||
} catch (e) {
|
||||
console.error("generateShareImage 绘制失败:", e);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -64,7 +64,7 @@ const onClick = async () => {
|
||||
<text>{{ data.weekArrow }}</text>
|
||||
<text>箭</text>
|
||||
</view>
|
||||
<view class="item-info" :style="{ justifyContent: 'flex-end' }">
|
||||
<view class="item-info">
|
||||
<text>{{ Math.round(data.weekArrow * 1.6) }}</text>
|
||||
<text>千卡</text>
|
||||
</view>
|
||||
@@ -112,7 +112,7 @@ const onClick = async () => {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
.rank-item > view:nth-child(2) > view:last-child > text:first-child {
|
||||
font-size: 26rpx;
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
@@ -129,13 +129,13 @@ const onClick = async () => {
|
||||
.item-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 22rpx;
|
||||
justify-content: flex-end;
|
||||
font-size: 20rpx;
|
||||
color: #777777;
|
||||
width: 18%;
|
||||
width: 20%;
|
||||
}
|
||||
.item-info > text:first-child {
|
||||
font-size: 26rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
margin-right: 5rpx;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { ref, onMounted } from "vue";
|
||||
import ScrollList from "@/components/ScrollList.vue";
|
||||
import PointRankItem from "@/components/PointRankItem.vue";
|
||||
import { getPointBookRankListAPI } from "@/apis";
|
||||
import { capsuleHeight } from "@/util";
|
||||
import { wxShare } from "@/util";
|
||||
import { sharePractiseData } from "@/canvas";
|
||||
|
||||
const list = ref([]);
|
||||
const mine = ref({
|
||||
averageRing: 0,
|
||||
});
|
||||
const loading = ref(false);
|
||||
|
||||
const onLoad = async (page) => {
|
||||
const result = await getPointBookRankListAPI(page);
|
||||
@@ -17,6 +20,20 @@ const onLoad = async (page) => {
|
||||
else list.value = list.value.concat(result.list);
|
||||
return result.list.length;
|
||||
};
|
||||
|
||||
const shareImage = async () => {
|
||||
if (loading.value || !mine.value.id) return;
|
||||
loading.value = true;
|
||||
await sharePractiseData("shareCanvas", mine.value);
|
||||
await wxShare("shareCanvas");
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
// onMounted(() => {
|
||||
// setTimeout(() => {
|
||||
// shareImage();
|
||||
// }, 1000);
|
||||
// });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -82,6 +99,15 @@ const onLoad = async (page) => {
|
||||
<PointRankItem v-for="item in list" :key="item.id" :data="item" />
|
||||
</ScrollList>
|
||||
</view>
|
||||
<button hover-class="none" class="share-btn" @click="shareImage">
|
||||
<image src="../static/share-icon.png" mode="widthFix" />
|
||||
</button>
|
||||
<canvas
|
||||
class="share-canvas"
|
||||
id="shareCanvas"
|
||||
type="2d"
|
||||
style="width: 375px; height: 460px"
|
||||
></canvas>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
@@ -151,7 +177,8 @@ const onLoad = async (page) => {
|
||||
line-height: 80rpx;
|
||||
}
|
||||
.rank-title-bar > text:nth-child(1) {
|
||||
width: 15%;
|
||||
width: calc(15% - 30rpx);
|
||||
padding-left: 30rpx;
|
||||
}
|
||||
.rank-title-bar > text:nth-child(2) {
|
||||
flex: 1;
|
||||
@@ -167,4 +194,13 @@ const onLoad = async (page) => {
|
||||
border-radius: 25rpx;
|
||||
margin: 0 25rpx;
|
||||
}
|
||||
.share-btn {
|
||||
position: fixed;
|
||||
right: 25rpx;
|
||||
bottom: 25rpx;
|
||||
}
|
||||
.share-btn > image {
|
||||
width: 116rpx;
|
||||
height: 116rpx;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -481,7 +481,7 @@ onShareTimeline(() => {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.statistics-item > text:nth-child(2) {
|
||||
line-height: 62rpx;
|
||||
transform: translateY(16rpx);
|
||||
}
|
||||
.statistics-item > text:nth-child(3) {
|
||||
width: 100%;
|
||||
@@ -658,7 +658,7 @@ onShareTimeline(() => {
|
||||
flex: 1;
|
||||
}
|
||||
.rank-title-bar > text:nth-child(3) {
|
||||
width: 18%;
|
||||
width: 16%;
|
||||
}
|
||||
.rank-title-bar > text:nth-child(4) {
|
||||
width: 27%;
|
||||
@@ -669,8 +669,8 @@ onShareTimeline(() => {
|
||||
border-radius: 8rpx;
|
||||
border: 1rpx solid #777777;
|
||||
height: 20rpx;
|
||||
line-height: 20rpx !important;
|
||||
padding: 8rpx;
|
||||
transform: translateY(8rpx);
|
||||
line-height: 20rpx;
|
||||
transform: translateY(6rpx) !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user