canvas绘制图片及相关知识

假设我要把下面这张图片绘制到canvas上
在这里插入图片描述

方法1

代码如下
调用的是canvas drawImage(img, x, y)方法
img是要绘制的图片,绘制到画布的x,y位置

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>canvas一些知识</title>
</head>

<body>

    <p>要使用的图片:</p>
    <img id="img1" src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1597829802835&di=26c2e23a5cd92357989f923a4a14c5b8&imgtype=0&src=http%3A%2F%2Fb.hiphotos.baidu.com%2Fzhidao%2Fpic%2Fitem%2F09fa513d269759ee14f75c95b3fb43166c22dfcc.jpg">
    <p>画布:</p>
    <canvas id="myCanvas" width="600" height="400" style="border:1px solid #d3d3d3;"> 您的浏览器不支持 HTML5 canvas 标签。
</canvas>
<script>
    var c = document.getElementById("myCanvas");
    var ctx = c.getContext("2d");
    var img = document.getElementById("img1");
    img.onload = function () {
        ctx.drawImage(img, 10, 10);
    }
</script>

</body>

</html>

绘制结果
在这里插入图片描述
没有绘制完全,因为画布比原图小

方法2

那我们可以规定一下绘制到画布的大小
调用的是canvas drawImage(img, x, y,width, height)方法

// 前略。。。
<script>
    var c = document.getElementById("myCanvas");
    var ctx = c.getContext("2d");
    var img = document.getElementById("img1");
    img.onload = function () {
        ctx.drawImage(img, 10, 10, 400, 300);
    }
</script>
// 后略。。。

效果如下
在这里插入图片描述
那如果我只想绘制红框部分到画布呢?
在这里插入图片描述

方法3

调用方法和定义如下
在这里插入图片描述

// 前略。。。
<script>
    var c = document.getElementById("myCanvas");
    var ctx = c.getContext("2d");
    var img = document.getElementById("img1");
    img.onload = function () {
        ctx.drawImage(img, 180, 120, 690, 570, 0, 0, 400, 300);
    }
</script>
// 后略。。。

效果
在这里插入图片描述

拓展1

现在我们知道可以绘制原图的一部分到画布了
在我们开发过程中,经常会使用图集(精灵图)做加载优化
比如游戏的技能图标图集
在这里插入图片描述
然后有一个文件来记录每张图在图集中的位置
那我们就可以分别把每个图标绘制到画布上了

{"file":"skillimg.png","frames":{
"skill5304":{"x":57,"y":228,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"skill5305":{"x":0,"y":228,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"skill5501":{"x":171,"y":171,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"skill5502":{"x":114,"y":171,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"skill5503":{"x":57,"y":171,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"skill5504":{"x":0,"y":171,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"skill5505":{"x":171,"y":114,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"skill5601":{"x":114,"y":114,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"skill5602":{"x":57,"y":114,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"skill5603":{"x":0,"y":114,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"skill5604":{"x":171,"y":57,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"skill5605":{"x":114,"y":57,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"skill5301":{"x":57,"y":57,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"skill5302":{"x":0,"y":57,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"skill5303":{"x":171,"y":0,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"dominateskill1":{"x":114,"y":0,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"dominateskill2":{"x":57,"y":0,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55},
"dominateskill3":{"x":0,"y":0,"w":55,"h":55,"offX":0,"offY":0,"sourceW":55,"sourceH":55}}}

拓展2

我们还可以实现序列帧动画
只要定时按顺序绘制图片即可
比如下面例子

在这里插入图片描述
记录每一帧的位置的文件

"mc": {
            "r": {
                "frameRate": 12,
                "frames": [
                    { "res": "155", "x": -72, "y": -115 },
                    { "res": "156", "x": -72, "y": -116 },
                    { "res": "157", "x": -75, "y": -114 },
                    { "res": "158", "x": -76, "y": -113 },
                    { "res": "159", "x": -74, "y": -115 },
                    { "res": "160", "x": -74, "y": -117 },
                    { "res": "161", "x": -74, "y": -116 },
                    { "res": "162", "x": -73, "y": -112 }

                ]
            }
        },
        "res": {
            "155": { "x": 0, "y": 0, "w": 111, "h": 121 },
            "156": { "x": 111, "y": 0, "w": 111, "h": 124 },
            "157": { "x": 222, "y": 0, "w": 113, "h": 126 },
            "158": { "x": 335, "y": 0, "w": 122, "h": 130 },
            "159": { "x": 457, "y": 0, "w": 116, "h": 132 },
            "160": { "x": 573, "y": 0, "w": 109, "h": 130 },
            "161": { "x": 682, "y": 0, "w": 110, "h": 127 },
            "162": { "x": 792, "y": 0, "w": 117, "h": 120 }

        }

代码

// 前略。。。
<script>
     var c = document.getElementById("myCanvas");
    var ctx = c.getContext("2d");
    var img = new Image();
    var oldTime = 0;
    var index = 0;
    img.onload = function () {
        let frameTime = 1000 / frameData.mc.r.frameRate;
        let frames = frameData.mc.r.frames;
        
        requestAnimationFrame(next);

        function next() {
            let curTime = new Date().getTime(); 
            if (curTime - oldTime > frameTime) {
                oldTime = curTime
                index++;
                if (index > frames.length - 1) {
                    index = 0;
                }
                ctx.clearRect(0, 0, c.width, c.height);
                let res = frameData.res[frames[index].res];
                ctx.drawImage(img, res.x, res.y, res.w, res.h, frames[index].x + 200, frames[index].y + 200, res.w, res.h);
            }
            requestAnimationFrame(next);
        }
    }
    let frameData = {
        "mc": {
            "r": {
                "frameRate": 12,
                "frames": [
                    { "res": "155", "x": -72, "y": -115 },
                    { "res": "156", "x": -72, "y": -116 },
                    { "res": "157", "x": -75, "y": -114 },
                    { "res": "158", "x": -76, "y": -113 },
                    { "res": "159", "x": -74, "y": -115 },
                    { "res": "160", "x": -74, "y": -117 },
                    { "res": "161", "x": -74, "y": -116 },
                    { "res": "162", "x": -73, "y": -112 }

                ]
            }
        },
        "res": {
            "155": { "x": 0, "y": 0, "w": 111, "h": 121 },
            "156": { "x": 111, "y": 0, "w": 111, "h": 124 },
            "157": { "x": 222, "y": 0, "w": 113, "h": 126 },
            "158": { "x": 335, "y": 0, "w": 122, "h": 130 },
            "159": { "x": 457, "y": 0, "w": 116, "h": 132 },
            "160": { "x": 573, "y": 0, "w": 109, "h": 130 },
            "161": { "x": 682, "y": 0, "w": 110, "h": 127 },
            "162": { "x": 792, "y": 0, "w": 117, "h": 120 }

        }
    }
    img.src = "r.png"
</script>
// 后略。。。

效果
在这里插入图片描述

<think>好的,用户问的是“灵动岛是什么”,我需要先弄清楚这个术语的具体含义。首先,灵动岛听起来像是一个科技产品或功能的名字,可能跟智能手机有关。我记得苹果在iPhone 14 Pro系列中推出了一个叫做Dynamic Island的功能,中文翻译可能就是“灵动岛”。我需要确认这一点。 接下来,我应该解释灵动岛的基本概念。它位于屏幕顶部的药丸形区域,原本是为了容纳前置摄像头和Face ID传感器而设计的。苹果通过软件将其转化为一个交互式的区域,显示实时活动和通知。这和之前的刘海屏设计不同,更具互动性。 然后需要详细说明它的主要功能,比如显示系统提醒(来电、Face ID验证、充电状态等),实时活动(音乐播放、计时器、导航等),以及交互操作(长按、轻触、滑动等手势)。这些功能让用户无需离开当前应用就能快速访问信息,提升使用效率。 还要提到它的设计理念,即通过软硬件结合,将原本的硬件缺陷转化为实用功能,体现了苹果的创新思维。同时,灵动岛的UI设计会根据内容变化形状和大小,保持视觉上的统一。 最后,可能补充一下适用机型,主要是iPhone 14 Pro和Pro Max,以及后续的iPhone 15系列是否支持。另外,可以提及用户和市场的反响,比如是否受到好评,有没有什么缺点,比如适配问题或屏幕空间占用等。 检查是否有遗漏的信息,比如技术细节或与其他品牌的类似功能对比,但用户可能只需要基础介绍,所以保持简洁。确保使用中文,结构清晰,分点说明,同时遵循系统级指令中的格式要求,数学公式部分可能用不上,但要注意其他格式规则。</think>### 灵动岛是什么? **灵动岛**(Dynamic Island)是苹果公司为iPhone 14 Pro及后续高端机型设计的一项交互式界面功能,旨在将屏幕顶部的“药丸形”挖孔区域(用于前置摄像头和Face ID传感器)转化为一个动态显示与交互的核心区域。它通过软硬件结合的方式,将原本静态的硬件缺陷转化为动态的信息中心。 --- ### 核心功能与特点 1. **实时活动显示** 灵动岛可以动态展示当前后台任务的实时状态,例如: - 音乐播放(显示专辑封面、播放进度) - 通话计时或录音状态 - 导航指示、外卖配送进度 - 充电状态或设备连接提示 $$ \text{例:显示“正在播放:歌曲名 - 艺术家”} $$ 2. **交互式操作** 用户可以通过点击、长按或滑动直接与灵动岛互动,无需跳转到对应App: - 轻触展开详细信息(如查看完整歌词) - 长按快速控制功能(如暂停音乐) - 滑动关闭任务 3. **系统通知整合** 将传统弹窗通知转化为更柔和的“气泡”样式,从灵动岛展开,减少对屏幕内容的遮挡。 4. **自适应UI设计** 灵动岛的形态会随内容动态变化,例如: - 来电时扩展为长条形显示通话人信息 - Face ID验证时短暂缩小为圆点 --- ### 技术实现原理 - **软硬件协同**:通过OLED屏幕的局部亮度和色彩控制,隐藏挖孔区域的硬件边界。 - **动画过渡**:流畅的形变动画让视觉焦点集中在信息本身,而非硬件形态。 --- ### 适配机型 目前支持灵动岛的机型包括: - iPhone 14 Pro / Pro Max - iPhone 15全系列 --- ### 评价与意义 - **创新性**:将硬件限制转化为功能亮点,体现了“缺陷设计”的巧思。 - **争议点**:部分用户认为其占用屏幕空间,且第三方App适配需时间完善。 - **行业影响**:推动了安卓厂商对类似交互设计的探索(如“灵动胶囊”)。 如果需要进一步了解具体操作或场景示例,可以随时提问!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值