122 lines
2.6 KiB
Vue
122 lines
2.6 KiB
Vue
<template>
|
|
<view class="food-tile-icon" :class="[`food-tile-icon--${size}`]">
|
|
<text class="food-tile-icon__emoji">{{ fallbackIcon }}</text>
|
|
<image
|
|
v-if="src && !imageFailed"
|
|
class="food-tile-icon__img"
|
|
:src="src"
|
|
mode="aspectFit"
|
|
@error="onImageError"
|
|
/>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed, ref, watch } from 'vue'
|
|
import { getFoodImgUrl } from '../data/gameFoodImg.js'
|
|
|
|
const props = defineProps({
|
|
food: { type: [Object, String], default: null },
|
|
size: { type: String, default: 'tile' }
|
|
})
|
|
|
|
const imageFailed = ref(false)
|
|
|
|
const fallbackIcon = computed(() => {
|
|
if (typeof props.food === 'object' && props.food?.icon) return props.food.icon
|
|
return '🍽'
|
|
})
|
|
|
|
const src = computed(() => {
|
|
if (typeof props.food === 'object' && props.food?.img) return props.food.img
|
|
if (typeof props.food === 'object' && props.food?.icon) return getFoodImgUrl(props.food.icon)
|
|
return ''
|
|
})
|
|
|
|
watch(
|
|
() => src.value,
|
|
() => {
|
|
imageFailed.value = false
|
|
}
|
|
)
|
|
|
|
function onImageError() {
|
|
imageFailed.value = true
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.food-tile-icon {
|
|
position: relative;
|
|
box-sizing: border-box;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.food-tile-icon--tile {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
font-size: calc(var(--tile-emoji-size, 48px) * 0.6);
|
|
}
|
|
|
|
.food-tile-icon--tile .food-tile-icon__emoji,
|
|
.food-tile-icon--tile .food-tile-icon__img {
|
|
left: 50%;
|
|
top: 50%;
|
|
transform: translate(-50%, -50%);
|
|
width: 75%;
|
|
height: 75%;
|
|
z-index: 2;
|
|
}
|
|
|
|
/* 玻璃格上的食材图片:投影增强立体感(参考稿) */
|
|
.food-tile-icon--tile .food-tile-icon__img {
|
|
filter: drop-shadow(0 6rpx 10rpx rgba(0, 0, 0, 0.16));
|
|
}
|
|
|
|
.food-tile-icon--goal {
|
|
width: 40rpx;
|
|
height: 40rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.food-tile-icon--tooltip {
|
|
width: 36rpx;
|
|
height: 36rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.food-tile-icon__emoji {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 50%;
|
|
transform: translate(-50%, -50%);
|
|
font-size: inherit;
|
|
line-height: 1;
|
|
z-index: 1;
|
|
}
|
|
|
|
.food-tile-icon--goal .food-tile-icon__emoji,
|
|
.food-tile-icon--tooltip .food-tile-icon__emoji {
|
|
position: static;
|
|
transform: none;
|
|
font-size: 34rpx;
|
|
}
|
|
|
|
.food-tile-icon__img {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
z-index: 2;
|
|
display: block;
|
|
}
|
|
</style>
|