技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> JavaScript --> 用 JS 复制艺术

用 JS 复制艺术

浏览:1526次  出处信息
  • 原文地址(original source):http://jsart.co/11/replicating-art-with-js/

  • 作者(author):https://twitter.com/kodisha


  •    今天我发现了一副美丽的绘画,经过一番研究,我找到了名字和作者。

       jsart_infinite_dots-756x1024

  • YAYOI KUSAMA

  • Infinity-Dots [HOFS], 2014

  • Acrylic on canvas

  • 130.3 x 97 cm

  •    (顺便说一句,可以浏览相同作品集的其它作品)

       看起来真的不错,更重要的是,它貌似能够用 JavaScript 复制。

       我花了一些时间观察,决定使用最简单的方法——带有少许改动的、某种正弦函数。对于资源库,我打算用平常的 JS。

    细节

       首先,让我们放大、看下图片本身的细节。

       Screen-Shot-2015-05-25-at-4.53.57-PM

       我们能够注意到:

  • 稍微扭曲的圆

  • 它们有边界

  • 越小的圆,扭曲得越多

  •    本图或许给你留下这是一副“简单的”复制品,但不尽然。看下所有这些点,它们从来没有重叠。

       甚至它看起来有一些像正弦波的主风格,它更像是艺术家用大量点做的纵向条纹,然后只是耐心地填充了其余部分(我的看法,或许我完全错了)。我做了少量测试。我现在明白了,为了达到几近完美的复制,我将不得不引入某种 hit-test【注1】,或者保留事先画好的点的位置。

       我不想这样做,我想做一些类似于我能做的事情,只使用简单命令和纯粹的 JS。

    结果

       开干,我尝试了一些简单方法,下面是结果:

    刚开始,没有经验的尝试,用了简单的正弦函数。

刚开始,没有经验的尝试,用了简单的正弦函数。

   很明显这行不通,我尝试不覆盖圆,但是空隙太大了:

   Screen-Shot-2015-05-26-at-1.37.05-AM

   在接下来的截图里,我对空间做了尝试,只是当心不让圆重叠:

更好的结果,但是仍然离原作品相差甚远。更好的结果,但是仍然离原作品相差甚远。

   最后,加上一点点扭曲,变成了:

Screen-Shot-2015-05-26-at-2.51.26-AM-1024x706不太完美,但足以接近。全是代码的功劳。

   这是真正有趣的试验,即使我做不到在细节上做好复制,但是你能够用几行代码就能搞出某些真正好看的图像,这会给人留下深刻的印象。在我们的例子中,下面是输出最终图片的所有代码:

var canvas = document.getElementById('replica');
    var ctx = canvas.getContext('2d');
 
    var circle = function(radius, x, y) {
 
        ctx.fillStyle = '#b50024';
        ctx.strokeStyle = '#771522';
        ctx.beginPath();
        ctx.arc(x, y, radius, 0, Math.PI * 2);
        ctx.stroke();
        ctx.fill();
        ctx.closePath();
 
    };
 
    var lastX = 0;
    var fix = 0;
    var width = 500;
    var height = 677;
    for (var i = 0; i < width; i += 2) {
 
        var x = i / (width / 150);
        var radius = 6 / (3 * (Math.exp(Math.sin(x))));
 
        lastX = lastX + radius + radius + 3;
 
        for (var j = 4; j < height; j += 2) {
 
            var randOffset = ( 0.7 * radius) * Math.random();
            var deviation = j / (height / 10 * (2 *  height / j ));
            var dOffset = Math.cos(j/(height/4)) * ((3.4 + (1.4 * (j/height)))
                    * Math.exp(Math.cos(deviation))) * (1.5 + (2 * ((3.2 * (i / width)) )
                    * Math.exp(Math.sin(deviation))));
 
            if (j % 12 === 0) {
                if (radius >= 3.4) {
                    circle(radius, lastX - dOffset, j + randOffset);
                }
 
            } else {
                if (radius < (6 * Math.random())) {
                    circle(radius, lastX - dOffset, j + randOffset);
 
                }
            }
        }
    }

   本例的完整源代码,还可以点击在线 demo

   这是一次不同凡响的尝试。下次我将挑选一些不同的(但是同样有挑战性的)的例子,并尽量做同样的事情。

   更新:

   用户 blackle 在评论里留下了更好的实现,她的结果更加完美!

   orKSxcH

   太棒了!你可以访问她的 demo


  • 注1:In computer graphics programming, hit-testing (hit detection, picking, or pick correlation) is the process of determining whether a user-controlled cursor (such as a mouse cursor or touch-point on a touch-screen interface) intersects a given graphical object (such as a shape, line, or curve) drawn on the screen. http://en.wikipedia.org/wiki/Hit-testing

建议继续学习:

  1. vim的复制粘贴小结    (阅读:6465)
  2. VIM复制粘贴的那些事    (阅读:3976)
  3. MySQL5.5复制/同步的新特性及改进    (阅读:3706)
  4. MySQL Cluster 与 MongoDB 复制及分片设计及原理    (阅读:3209)
  5. MySQL复制的概述、安装、故障、技巧、工具    (阅读:3196)
  6. 快速复制一张大表讨论    (阅读:3136)
  7. [MySQL优化案例] — slave延迟很大优化方法    (阅读:2578)
  8. Google Docs Ctrl + C 技术浅析    (阅读:1767)
  9. 在 Linux 上复制和重命名文件    (阅读:752)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
后一篇:React初探 >>
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1