1. 修改index.html文件
html
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
2. 修改app.vue文件
设置html根元素字体大小:当屏幕宽度<=576px时,1rem = 1px;
html
<script setup>
import { RouterView } from 'vue-router'
import { ref, onMounted, onBeforeUnmount } from 'vue'
// 判断是否横屏
const isLandscape = ref(false)
// 判断是否横屏
const checkLandscape = () => {
isLandscape.value = (Math.abs(window.orientation) === 90)
}
// 设置html根元素字体大小:当屏幕宽度<=768px时,1rem = 1px;
// 手机<=480折叠屏手机768<=平板
const resize = () => {
const deviceWidth = window.innerWidth
// 375宽为视觉稿宽度
document.documentElement.style.fontSize = window.innerWidth >= 768 ? `${768 / 375}px` : `${deviceWidth / 375}px`
}
onMounted(() => {
resize()
window.addEventListener('resize', resize)
window.addEventListener('orientationchange', checkLandscape)
})
onBeforeUnmount(() => {
window.removeEventListener('resize', resize)
window.removeEventListener('orientationchange', checkLandscape)
})
</script>
<template>
<RouterView v-show="!isLandscape" />
<div v-show="isLandscape" class="tip">请切换至竖屏!</div>
</template>
<style scoped>
.tip {
color: #1989fa;
font-size: 40rem;
font-weight: bold;
}
</style>
3. 修改main.css文件
css
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-size: 14px;
line-height: 20px;
}
html,
body,
#app {
width: 100%;
height: 100%;
}
#app {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #f5f5f5;
}
4. demo
html
<template>
<div class="page">
<!-- 游戏画面 -->
<div class="game-container">
<canvas id="gameCanvas"></canvas>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import iceIcon from '@/assets/images/icons/ice.png'
let canvas // Canvas 对象
let ctx // 渲染上下文
let offScreenCanvas // 离屏canvas
let offScreenCtx // 离屏渲染上下文
const dpr = window.devicePixelRatio || 1 // 设备像素比
// 画布大小
let canvasWidth = 320 // px
let canvasHeight = 320 // px
// 已绘制的格子数,共 8 * 8 = 64
let gridFinishedNumber = 0
// 初始化canvas
function initCanvas() {
// 获取canvas元素
canvas = document.getElementById('gameCanvas')
// 获取渲染上下文
ctx = canvas.getContext('2d')
// * 设备像素比,绘制出来的图片更清晰
canvas.width = canvasWidth * dpr
canvas.height = canvasHeight * dpr
ctx.scale(dpr, dpr)
// 离屏canvas
offScreenCanvas = new OffscreenCanvas(canvasWidth * dpr, canvasHeight * dpr)
// 获取离屏渲染上下文
offScreenCtx = offScreenCanvas.getContext('2d')
offScreenCtx.scale(dpr, dpr)
// 绘制canvas
drawCanvas()
}
// 绘制canvas
function drawCanvas() {
// 清空画布
clearCanvas()
for (let i = 0; i < 8; i++) {
for (let j = 0; j < 8; j++) {
drawImage(iceIcon, j * 40, i * 40, 40, 40)
}
}
}
// 绘制图片
const drawImage = (image, x, y, width, height) => {
const img = new Image()
img.onload = () => {
offScreenCtx.drawImage(img, x, y, width, height)
gridFinishedNumber++
if (gridFinishedNumber === 64) {
console.log('绘制完成')
ctx.clearRect(0, 0, canvasWidth, canvasHeight)
// 绘制离屏canvas到主canvas
ctx.drawImage(offScreenCanvas, 0, 0, canvasWidth, canvasHeight)
}
}
img.src = image
}
// 异步绘制图片
const drawImageAsync = (image, x, y, width, height) => {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = () => {
offScreenCtx.drawImage(img, x, y, width, height)
resolve()
}
img.src = image
})
}
// 清空画布
function clearCanvas() {
// 清空离屏canvas
offScreenCtx.clearRect(0, 0, canvasWidth, canvasHeight)
// 已绘制的格子数,共 8 * 8 = 64
gridFinishedNumber = 0
}
onMounted(() => {
// 初始化canvas
initCanvas()
})
</script>
<style lang="scss" scoped>
.page {
width: 375rem;
height: 100%;
padding: 10rem;
display: flex;
flex-direction: column;
align-items: center;
background: white;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
overflow-x: hidden;
overflow-y: auto;
.game-container {
position: relative;
width: 320rem;
height: 320rem;
#gameCanvas {
width: 320rem;
height: 320rem;
will-change: transform;
transform: translate3d(0, 0, 0);
/* 防止背面抖动 */
backface-visibility: hidden;
animation: slideInCard 1s ease-out forwards;
z-index: 2;
}
}
}
@keyframes slideInCard {
from {
opacity: 0;
transform: translateX(100%);
}
to {
opacity: 1;
transform: translateX(0);
}
}
</style>