随机小猫生成器,使用原生js/canvas 给女儿画点小猫--6/1000

我是天元,立志做1000个有趣的项目的前端,公众号:前端cssandjs

如果你喜欢的话,请点赞,收藏,转发

背景

在以前有一个很火的养猫项目,会随机生成各种猫的图案,鉴于我女儿非常喜欢卡通猫,所以我想帮她也画一批随机的猫。

首先用ai生成一张猫的图片

技术方案

其实最好的方案是使用svg,但是我真的没有办法画出来猫的全部svg,所以我想是不是可以使用一个简单的办法。 按照图片上的信息来说,分成3个部分

一个完整的图片样式,通过背景,花纹,边框三部分组成。

那么我们只要实现了这几部分,然后叠加上去就可以了。

例如一条没有花纹的尾巴,那么只需要

一张背景图片改变颜色,然后加上边框,即可自动生成。

所以我们先把猫的所有需要渲染的部分,进行切割,拆成底色和边框两部分。

具体实现

加载图片

js 复制代码
export function createImage(src: string): Promise<HTMLImageElement> {
  return new Promise((resolve, reject) => {
   
    const img = new Image();
    img.src = src;
    img.onload = () => {
      resolve(img);
    };
    img.onerror = (e) => {
      reject(e);
    };
  });
}

加载图片需要保证图片已经加载成功,所以封装一个promise,在图片资源加载完成后返回图片信息。

图片着色

js 复制代码
export function fillColor(
  imgUrl: string,
  color: string
): Promise<HTMLImageElement | null> {
  return createImage(imgUrl).then((img) => {
    if (!img) {
      return null;
    }
    const canvas: HTMLCanvasElement = document.createElement(
      "canvas"
    ) as HTMLCanvasElement;
    const context: CanvasRenderingContext2D = canvas.getContext(
      "2d"
    ) as CanvasRenderingContext2D;

    canvas.width = img.width;
    canvas.height = img.height;

    context.fillStyle = color;

    context.fillRect(0, 0, img.width, img.height);

    context.globalCompositeOperation = "destination-in";

    context.drawImage(img, 0, 0, img.width, img.height);

    context.globalCompositeOperation = "source-over";

    const finnalImage = canvas.toDataURL();

    return createImage(finnalImage);
  });
}

这里最关键的代码在于context.globalCompositeOperation = "destination-in",它的作用在于讲目标图形与源图形合并,并保留源图形。 整体代码的过程为先绘制一个矩形填充整体区域即背景,然后设定为destination-in模式,绘制图片,此时经过叠加,会保留图片绘制区域内的背景。

在绘制完成后将globalCompositeOperation修改为默认的source-over,并将图片通过toDataURL转成转成base64供绘制使用

绘制图片

绘制边框比较简单,直接使用context.drawImage即可,将着色后的背景图及边框依次绘制,即可得到一个改变颜色图片。

颜色选择 hsl

如果随机一个rgb颜色,可能存在颜色过亮或者过暗的情况。 我们更希望以一种颜色比较柔和的方式呈现,所以不适用rgb颜色,改为hsl颜色。 hsl是将rgb颜色变为坐标显示的一种颜色表现方式。 可以看到,亮度(light ness)越低的地方,颜色越暗,越高的地方,颜色越亮。 饱和度(saturation)越靠外的地方,颜色越鲜艳,所以我们可以设定一定的范围取值,用来约束颜色的色彩范围。

js 复制代码
export function getColor() {
  return (
    "hsl(" +
    360 * Math.random() +
    "," +
    // (25 + 70 * Math.random()) +
    100 * Math.random() +
    "%," +
    // (70 + 10 * Math.random()) +
    100 * Math.random() +
    "%)"
  );
}

此时获取到颜色色值更符合我们的审美。

花纹生成

花纹,我们可以直接使用如上述描述的方式,通过图片的形式生成,在头部我也尝试使用了一种随机的圆形用来模拟猫的脸部。灵感来源于起司猫。

可以看到基本的图形就是两个圆形的叠加,所以我用了两个圆来模拟各种情况

js 复制代码
// 圆形
  context.beginPath();
  if (side !== 3) {
    const randomHeight = Math.floor(Math.random() * 120);
    if (side === 0) {
      // 左半边
      context.arc(40, 0, 240, 0, 2 * Math.PI);
    } else if (side === 1) {
      // 右半边
      context.arc(460, 0, 240, 0, 2 * Math.PI);
    } else if (side === 2) {
      // 全部
      context.arc(40, 0, 240 + randomHeight, 0, 2 * Math.PI);
      context.arc(460, 0, 240 + randomHeight, 0, 2 * Math.PI);
    }
  }

这里用半圆,两个圆,没有圆来模拟三种情况。

end 最终效果

我是天元,立志做1000个有趣的项目的前端,公众号:前端cssandjs

如果你喜欢的话,请点赞,收藏,转发

相关推荐
极客密码4 小时前
感谢雷总!Mimo大模型价值¥659/月的 MAX 套餐,让我免费领到了!
前端·ai编程·claude
深念Y5 小时前
我明白为什么B站没法在浏览器开直播了——Windows Chrome推流踩坑全记录
前端·chrome·webrtc·浏览器·srs·直播·flv
zhangxingchao5 小时前
AI应用开发七:可以替代 RAG 的技术
前端·人工智能·后端
Sun@happy6 小时前
现代 Web 前端渗透——基础篇(1)
前端·web安全
希冀1236 小时前
【CSS学习第十一篇】
前端·css·学习
隔窗听雨眠6 小时前
doctype、charset、meta如何控制整个渲染流水线
java·服务器·前端
kyriewen6 小时前
写组件文档写到吐?我用AI自动生成Storybook,同事以后直接抄
前端·javascript·面试
excel7 小时前
🧠 Prisma 表名大写 vs SQL 导出小写问题深度解析(附踩坑与解决方案)
前端·后端
周淳APP7 小时前
【前端工程化原理通识:从源头到运行时的理论阐述】
前端·编译·打包·前端工程化
五点六六六7 小时前
你敢信这是非Native页面写出来的渐变效果吗🌝(底层原理解析
前端·javascript·面试