Canvas适配手机端

Canvas适配困境

最近做了个H5小游戏,它的主页的html代码如下:

<DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="HandheldFriendly" content="true">
    <title>React gametitle>
head>
<body>
    <div id="container">
        <div id="root">div>
        <canvas id="canvas" width=600 height=900>Canvas not supportedcanvas>
    div>

    <script src="common.js" defer async>script>
    <script src="index.bundle.js" defer async>script> 
body>
html>

这里我设置了meta标签, 告诉浏览器使用设备的宽度作为视图宽度(width=device-width)并禁止缩放(user-scalable=no),
屏幕按1:1的尺寸显示,在iPhone和其他智能手机提供全视图的浏览器,禁止用户缩放页面。

Canvas两套尺寸

CSS设置canvas元素大小 与直接设置属性相比,其差别是基于这样一个事实:
canvas元素实际有两套尺寸。
一个是元素本身大小,
一个是元素绘图表面drawing surface的大小
设置元素的width 和height 实际是同时设置 元素本身大小和 元素绘图表面的大小
而CSS设置,只是元素大小,绘图表面不影响,依然是默认的 300X150px
有趣的事情发生了,但当canvas元素大小不符合绘图表面的大小时就会对 绘图表面进行缩放使得它符合元素的大小!

警告浏览器自动缩放Canvas
通过width与height属性 而非CSS修改canvas元素的大小,。
使用CSS会导致浏览器缩放绘图表面大小!

这是当你没有设置width和height的时候。
默认是300X150
Canvas适配手机端_第1张图片

此时如果你用CSS设置width和height:
Canvas适配手机端_第2张图片

所以只是拉伸了绘图表面,本身的绘图表面仍然是300X150

解决方法

针对这个问题,我决定在head标签中再添加一个js文件用来
适配响应式。
首先要判断是在PC浏览器还是移动端打开的。

我们要在代码中检测视口大小,对于PC浏览器而言
视口和浏览器窗口的大小是基本一致的。
当然这是在margin和padding为0时,html和body
元素的大小和浏览器是一致的。

移动端视口

移动端中分视觉视口和理想视口。
视觉视口: 用户正在看到的网站的区域,我们可以通过缩放去操作视觉视口但是不会影响布局视口

理想视口,对设备来讲,是最理想的视口尺寸。
显示在理想视口中的网站拥有最理想的宽度,不需要缩放。
但只有当网站是手机(或者平板)的时候,才应该使用理想视口。

使用navigator的 UA检测方法

var ua=navigator.userAgent;
var system={
    win:false,
    mac:false,
    x11:false,
    //mobile
    iphone:false,
    ipad:false,
    ios:false,
    android:false,
    winMobile:false
};

//
var p=navigator.platform;
system.win=p.indexOf('Win')==0;
system.mac=p.indexOf('Mac')==0;
system.x11=(p=='x11')||(p.indexOf('Linux')==0);

system.iphone=ua.indexOf('iPhone')>-1;
system.ipad=ua.indexOf('iPad')>-1;
system.android=ua.indexOf('Android')>-1;

如果是PC浏览器我们设置canvas的
width 600px
height 900px那么就按这个显示。

但是如果检测到是移动端那么就把viewport的宽和高赋给canvas的 width 和 height。
代码如下:

/**
 *
 * 识别移动设备
 * 检测相应的设备。
 * */

var canvas=document.getElementById('canvas');

var ua=navigator.userAgent;
var system={
    win:false,
    mac:false,
    x11:false,
    //mobile
    iphone:false,
    ipad:false,
    ios:false,
    android:false,
    winMobile:false
};

//
var p=navigator.platform;
system.win=p.indexOf('Win')==0;
system.mac=p.indexOf('Mac')==0;
system.x11=(p=='x11')||(p.indexOf('Linux')==0);

system.iphone=ua.indexOf('iPhone')>-1;
system.ipad=ua.indexOf('iPad')>-1;
system.android=ua.indexOf('Android')>-1;

function getViewPort(){
    var viewHeight=window.innerHeight||document.documentElement.clientHeight;
    var viewWidth=window.innerWidth||document.documentElement.clientWidth;
    console.log(viewHeight,viewWidth);
    if(system.iphone){
        //alert(viewWidth,viewHeight);
        document.body.style.width=viewWidth;
        canvas.width=viewWidth;
        canvas.height=viewHeight;
    }
    else if(system.win){
        canvas.width=600;
        canvas.height=900;
    }
}

getViewPort();

显然我们可以根据这个viewport的大小来设置width和height。
canvas显然是可以响应式的根据不同设备的视口大小来设置canvas的宽高。
而且用JS设置这个宽高,也不会像用CSS那样造成视图拉伸的不良效果。

你可能感兴趣的:(前端)