细节优化

This commit is contained in:
kron
2026-01-05 18:03:47 +08:00
parent 3364aac93d
commit f7c24680cb
4 changed files with 109 additions and 12 deletions

View File

@@ -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);
}
};

View File

@@ -64,7 +64,7 @@ const onClick = async () => {
<text>{{ data.weekArrow }}</text> <text>{{ data.weekArrow }}</text>
<text></text> <text></text>
</view> </view>
<view class="item-info" :style="{ justifyContent: 'flex-end' }"> <view class="item-info">
<text>{{ Math.round(data.weekArrow * 1.6) }}</text> <text>{{ Math.round(data.weekArrow * 1.6) }}</text>
<text>千卡</text> <text>千卡</text>
</view> </view>
@@ -112,7 +112,7 @@ const onClick = async () => {
margin-left: 20rpx; margin-left: 20rpx;
} }
.rank-item > view:nth-child(2) > view:last-child > text:first-child { .rank-item > view:nth-child(2) > view:last-child > text:first-child {
font-size: 26rpx; font-size: 30rpx;
color: #333333; color: #333333;
margin-bottom: 5rpx; margin-bottom: 5rpx;
} }
@@ -129,13 +129,13 @@ const onClick = async () => {
.item-info { .item-info {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: flex-end;
font-size: 22rpx; font-size: 20rpx;
color: #777777; color: #777777;
width: 18%; width: 20%;
} }
.item-info > text:first-child { .item-info > text:first-child {
font-size: 26rpx; font-size: 28rpx;
color: #333333; color: #333333;
margin-right: 5rpx; margin-right: 5rpx;
} }

View File

@@ -1,14 +1,17 @@
<script setup> <script setup>
import { ref } from "vue"; import { ref, onMounted } from "vue";
import ScrollList from "@/components/ScrollList.vue"; import ScrollList from "@/components/ScrollList.vue";
import PointRankItem from "@/components/PointRankItem.vue"; import PointRankItem from "@/components/PointRankItem.vue";
import { getPointBookRankListAPI } from "@/apis"; import { getPointBookRankListAPI } from "@/apis";
import { capsuleHeight } from "@/util"; import { capsuleHeight } from "@/util";
import { wxShare } from "@/util";
import { sharePractiseData } from "@/canvas";
const list = ref([]); const list = ref([]);
const mine = ref({ const mine = ref({
averageRing: 0, averageRing: 0,
}); });
const loading = ref(false);
const onLoad = async (page) => { const onLoad = async (page) => {
const result = await getPointBookRankListAPI(page); const result = await getPointBookRankListAPI(page);
@@ -17,6 +20,20 @@ const onLoad = async (page) => {
else list.value = list.value.concat(result.list); else list.value = list.value.concat(result.list);
return result.list.length; 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> </script>
<template> <template>
@@ -82,6 +99,15 @@ const onLoad = async (page) => {
<PointRankItem v-for="item in list" :key="item.id" :data="item" /> <PointRankItem v-for="item in list" :key="item.id" :data="item" />
</ScrollList> </ScrollList>
</view> </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> </scroll-view>
</template> </template>
@@ -151,7 +177,8 @@ const onLoad = async (page) => {
line-height: 80rpx; line-height: 80rpx;
} }
.rank-title-bar > text:nth-child(1) { .rank-title-bar > text:nth-child(1) {
width: 15%; width: calc(15% - 30rpx);
padding-left: 30rpx;
} }
.rank-title-bar > text:nth-child(2) { .rank-title-bar > text:nth-child(2) {
flex: 1; flex: 1;
@@ -167,4 +194,13 @@ const onLoad = async (page) => {
border-radius: 25rpx; border-radius: 25rpx;
margin: 0 25rpx; margin: 0 25rpx;
} }
.share-btn {
position: fixed;
right: 25rpx;
bottom: 25rpx;
}
.share-btn > image {
width: 116rpx;
height: 116rpx;
}
</style> </style>

View File

@@ -481,7 +481,7 @@ onShareTimeline(() => {
margin-right: 10rpx; margin-right: 10rpx;
} }
.statistics-item > text:nth-child(2) { .statistics-item > text:nth-child(2) {
line-height: 62rpx; transform: translateY(16rpx);
} }
.statistics-item > text:nth-child(3) { .statistics-item > text:nth-child(3) {
width: 100%; width: 100%;
@@ -658,7 +658,7 @@ onShareTimeline(() => {
flex: 1; flex: 1;
} }
.rank-title-bar > text:nth-child(3) { .rank-title-bar > text:nth-child(3) {
width: 18%; width: 16%;
} }
.rank-title-bar > text:nth-child(4) { .rank-title-bar > text:nth-child(4) {
width: 27%; width: 27%;
@@ -669,8 +669,8 @@ onShareTimeline(() => {
border-radius: 8rpx; border-radius: 8rpx;
border: 1rpx solid #777777; border: 1rpx solid #777777;
height: 20rpx; height: 20rpx;
line-height: 20rpx !important;
padding: 8rpx; padding: 8rpx;
transform: translateY(8rpx); line-height: 20rpx;
transform: translateY(6rpx) !important;
} }
</style> </style>