Как я могу понять следующий SVG-код?

#svg

#svg

Вопрос:

У меня есть код с веб-сайта, и похоже, что он должен быть простым, но слишком простым для SVG. Как я могу определить, действительно ли это SVG, и что он делает? Меня особенно интересует то, что выглядит как вложенные amp; и точки[.], затем разделить, сопоставить.

Фрагмент:

 // the shape of the dragon, converted from a SVG image
  '! ((amp;(amp;*$($,amp;.)/-.0,4%3"7$;(@/EAA<?:<9;;88573729/7,6(8amp;;'.split("").map(function(a,i) {
  shape[i] = a.charCodeAt(0) - 32;
});
 

Полный код:

 //7 Dragons
//Rauri
// full source for entry into js1k dragons: http://js1k.com/2014-dragons/demo/1837

// thanks to simon for grunt help and sean for inspiration help

// js1k shim

var a = document.getElementsByTagName('canvas')[0];
var b = document.body;
var d = function(e){ return function(){ e.parentNode.removeChild(e); }; }(a);
// unprefix some popular vendor prefixed things (but stick to their original name)
var AudioContext =
    window.AudioContext ||
    window.webkitAudioContext;
var requestAnimationFrame =
    window.requestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    function(f){ setTimeout(f, 1000/30); };
// stretch canvas to screen size (once, wont onresize!)
a.style.width = (a.width = innerWidth - 0)   'px';
a.style.height = (a.height = innerHeight - 0)   'px';

var c = a.getContext('2d');

// end shim


var sw = a.width, 
sh = a.height, 
M = Math,
Mc = M.cos,
Ms = M.sin,
ran = M.random,
pfloat = 0, 
pi = M.PI, 
dragons = [], 
shape = [],


loop = function() {

  a.width = sw; // clear screen

  for ( j = 0; j < 7; j  ) {
    if ( !dragons[j] ) dragons[j] = dragon(j); // create dragons initially
    dragons[j]();
  }

  pfloat  ;

  requestAnimationFrame(loop);

},


dragon = function(index) {

  var scale = 0.1   index * index / 49, 
    gx = ran() * sw / scale, 
    gy = sh / scale, 
    lim = 300, // this gets inlined, no good!
    speed = 3   ran() * 5, 
    direction = pi, //0, //ran() * pi * 2, //ran(0,TAU), 
    direction1 = direction, 
    spine = [];

  return function() {

    // check if dragon flies off screen 
    if (gx < -lim || gx > sw / scale   lim || gy < -lim || gy > sh / scale   lim) {

      // flip them around

      var dx = sw / scale / 2 - gx,
        dy = sh / scale / 2 - gy;

      direction = direction1 = M.atan(dx/dy)   (dy < 0 ? pi : 0);

    } else {

       direction1  = ran() * .1 - .05;

       direction -= (direction - direction1) * .1;

    }

    // move the dragon forwards
    gx  = Ms(direction) * speed;
    gy  = Mc(direction) * speed;

    // calculate a spine - a chain of points
    // the first point in the array follows a floating position: gx,gy
    // the rest of the chain of points following each other in turn

    for (i=0; i < 70; i  ) {

      if (i) {

        if (!pfloat) spine[i] = {x: gx, y: gy}

        var p = spine[i - 1],
          dx = spine[i].x - p.x,
          dy = spine[i].y - p.y,
          d = M.sqrt(dx * dx   dy * dy),
          perpendicular = M.atan(dy/dx)   pi / 2   (dx < 0 ? pi : 0);

        // make each point chase the previous, but never get too close
        if (d > 4) {
          var mod = .5;
        } else if (d > 2){
          mod = (d - 2) / 4;
        } else {
          mod = 0;
        }

        spine[i].x -= dx * mod;
        spine[i].y -= dy * mod;
        // perpendicular is used to map the coordinates on to the spine
        spine[i].px = Mc(perpendicular);
        spine[i].py = Ms(perpendicular);

        if (i == 20) { // average point in the middle of the wings so the wings remain symmetrical
          var wingPerpendicular = perpendicular;
        }

      } else {

        // i is 0 - first point in spine
        spine[i] = {x: gx, y: gy, px: 0, py: 0}; 

      }

    }

    // map the dragon to the spine
    // the x co-ordinates of each point of the dragon shape are honoured
    // the y co-ordinates of each point of the dragon are mapped to the spine

    c.moveTo(spine[0].x,spine[0].y)

    for (i=0; i < 154; i =2) { // shape.length * 2 - it's symmetrical, so draw up one side and back down the other

      if (i < 77 ) { // shape.length
        // draw the one half from nose to tail
        var index = i; // even index is x, odd (index   1) is y of each coordinate
        var L = 1;
      } else {
        // draw the other half from tail back to nose
        index = 152 - i;  
        L = -1;
      }

      var x = shape[index];

      var spineNode = spine[shape[index 1]]; // get the equivalent spine position from the dragon shape

      if (index >= 56) {  // draw tail

        var wobbleIndex = 56 - index; // table wobbles more towards the end

        var wobble = Ms(wobbleIndex / 3   pfloat * 0.1) * wobbleIndex * L;

        x = 20 - index / 4   wobble;

        // override the node for the correct tail position
        spineNode = spine[ index * 2 - 83 ];

      } else if (index > 13) {  // draw "flappy wings"

        // 4 is hinge point
        x = 4   (x-4) * (Ms(( -x / 2   pfloat) / 25 * speed / 4)   2) * 2; // feed x into sin to make wings "bend"

        // override the perpindicular lines for the wings
        spineNode.px = Mc(wingPerpendicular);
        spineNode.py = Ms(wingPerpendicular);

      }

      c.lineTo(
        (spineNode.x   x * L * spineNode.px) * scale, 
        (spineNode.y   x * L * spineNode.py) * scale
      );

    }

    c.fill();

  }

}

// the shape of the dragon, converted from a SVG image
  '! ((amp;(amp;*$($,amp;.)/-.0,4%3"7$;(@/EAA<?:<9;;88573729/7,6(8amp;;'.split("").map(function(a,i) {
  shape[i] = a.charCodeAt(0) - 32;
});



loop();
 

Комментарии:

1. Это не SVG — это canvas (вы можете легко увидеть это с помощью инспектора страниц)

Ответ №1:

Хотя контекст, в котором это используется, является <canvas> , источником вполне может быть SVG <polyline> .

На первом шаге буквы сопоставляются с цифрами. Немного затемнения, но ничего серьезного: получите число, представляющее букву, и запишите его в массив.

 const shape = [];

'! ((amp;(amp;*$($,amp;.)/-.0,4%3"7$;(@/EAA<?:<9;;88573729/7,6(8amp;;'.split("").map(function(a,i) {
  shape[i] = a.charCodeAt(0) - 32;
});
 

результаты в виде массива

 [1,0,8,8,6,8,6,10,4,8,4,12,6,14,9,15,13,14,16,12,20,5,19,2,23,4,27,8,32,15,37,33,33,28,31,26,28,25,27,27,24,24,21,23,19,23,18,25,15,23,12,22,8,24,6,27]
 

Теперь просто запишите этот массив в points атрибут a polyline , объединив числа с пробелом:

 const outline = document.querySelector('#outline');

const shape = [];
'! ((amp;(amp;*$($,amp;.)/-.0,4%3"7$;(@/EAA<?:<9;;88573729/7,6(8amp;;'.split("").map(function(a,i) {
  shape[i] = a.charCodeAt(0) - 32;
});

outline.setAttribute('points', shape.join(' ')) 
 #outline {
    stroke: black;
    stroke-width: 0.5;
    fill:none;
} 
 <svg viewBox="0 0 77 77" width="300" height="300">
    <polyline id="outline" />
</svg> 

и вы получаете базовый контур (половину) дракона. Остальное — повторение и преобразование, чтобы сделать вещи немного более сложными.

Комментарии:

1. прохладный. Спасибо… это очень помогает … итак, что теперь делают функции .map и .split ? Например, это сопоставление функции с «a», а затем с формой [i]?

2. Вы можете легко посмотреть, что map() и split() сделать самостоятельно.