Как сделать анимированную пунктирную линию SVG? - PullRequest
1 голос
/ 21 июня 2019

Я пытался создать анимированную пунктирную линию в HTML (SVG) / CSS / JS.

Это моя первая svg анимация ... и понятно ... я ничего не понимаю.

Прежде всего, это моя пунктирная линия:

<svg id="bf7de8ba-cf75-48ab-a36c-06f8d86635d5" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 690.814 824.302">
  <defs>
    <style>
      .a00cb6af-c716-4d00-9962-797e598003da,
      .a6fde9f6-9a2f-4715-ac34-678948a4d015,
      .b963f74d-80cb-4571-80bd-9cf5cd28cce2 {
        fill:none;
        stroke-miterlimit:10;
        stroke-width:6px;
      }
      .a6fde9f6-9a2f-4715-ac34-678948a4d015 {
        stroke:url(#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0);
      }
      .b963f74d-80cb-4571-80bd-9cf5cd28cce2 {
        stroke-dasharray:30.322 50.536;
        stroke:url(#a958eb71-8928-4250-a898-e2a9df336375);
      }
      .a00cb6af-c716-4d00-9962-797e598003da {
        stroke:url(#a8cb66bd-35fa-45ad-b9b6-1af210f764d2);
      }
    </style>
    <linearGradient id="bef7cd12-3404-46dc-ac0f-c9d91ddd83d0" x1="60.835" y1="123.864" x2="751.668" y2="123.864" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#ec6608"/>
      <stop offset="0.494" stop-color="#c33089"/>
      <stop offset="1" stop-color="#662483"/>
    </linearGradient>
    <linearGradient id="a958eb71-8928-4250-a898-e2a9df336375" x1="60.835" y1="541.828" x2="751.668" y2="541.828" xlink:href="#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0"/>
    <linearGradient id="a8cb66bd-35fa-45ad-b9b6-1af210f764d2" x1="60.835" y1="932.54" x2="751.668" y2="932.54" xlink:href="#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0"/>
  </defs>
  <path class="a6fde9f6-9a2f-4715-ac34-678948a4d015" d="M748.213,116.426c.215,4.461.381,9.478.436,14.992" transform="translate(-60.835 -116.281)"/>
  <path id="pathRecrut" class="b963f74d-80cb-4571-80bd-9cf5cd28cce2" d="M745.947,181.853c-3.573,34.83-7.4,65.457-20.713,85.466-36.276,54.511-150.309,41.2-247.4,29.872-73.484-8.575-74.824-17.343-139.4-21.446-87.16-5.538-141.016-8.96-191.49,24.51-48.083,31.886-87.4,93.472-82.723,159.319.847,11.934,4.189,59.01,39.83,91.915,35.144,32.448,81.33,32.315,131.744,32.171,53.366-.154,56.932-10.359,130.213-18.383,52.244-5.721,100.335-10.606,160.085,1.532,36.964,7.508,74.081,20.657,109.532,43.659,26.491,17.189,49.773,32.776,59.745,62.809,1.48,4.457,13.436,42.337-6.894,72.766-14.348,21.475-39.623,31.524-81.957,36.766-67.779,8.391-105.681-4.654-182.3-16.086-41.6-6.206-132.521-17.593-227.49-.766-22.971,4.071-60.931,12.4-91.149,42.894-7.9,7.968-23.347,23.951-29.872,49.787a99.225,99.225,0,0,0-1.1,42.916" transform="translate(-60.835 -116.281)"/>
  <path class="a00cb6af-c716-4d00-9962-797e598003da" d="M81.983,925.674a117,117,0,0,0,6.74,13.39" transform="translate(-60.835 -116.281)"/>
</svg>

см. На коде ручки: https://codepen.io/Unrillaz/pen/gNmgjW

Я сделал это с помощью Illustrator (Adobe).

Итак, я попытался анимировать эту строку и следовал этому уроку по CSS-TRICKS: https://css -tricks.com / scroll-drawing /

И .... ТАДА! Что у меня есть:

             // Get a reference to the <path>
var path = document.querySelector('#pathRecrut');

// Get length of path... ~577px in this case
var pathLength = path.getTotalLength();

// Make very long dashes (the length of the path itself)
path.style.strokeDasharray = pathLength + ' ' + pathLength;

// Offset the dashes so the it appears hidden entirely
path.style.strokeDashoffset = pathLength;

// Jake Archibald says so
// https://jakearchibald.com/2013/animated-line-drawing-svg/
path.getBoundingClientRect();

// When the page scrolls...
window.addEventListener("scroll", function(e) {
 
  // What % down is it? 
  // /2191860/kross-brauzernyi-metod-dlya-opredeleniya-protsenta-vertikalnoi-prokrutki-v-javascript#2191868
  // Had to try three or four differnet methods here. Kind of a cross-browser nightmare.
  var scrollPercentage = (document.documentElement.scrollTop + document.body.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
    
  // Length to offset the dashes
  var drawLength = pathLength * scrollPercentage;
  
  // Draw in reverse
  path.style.strokeDashoffset = pathLength - drawLength;
    
  // When complete, remove the dash array, otherwise shape isn't quite sharp
 // Accounts for fuzzy math
  if (scrollPercentage >= 0.99) {
    path.style.strokeDasharray = "none";
    
  } else {
    path.style.strokeDasharray = pathLength + ' ' + pathLength;
  }
  
});
<svg id="bf7de8ba-cf75-48ab-a36c-06f8d86635d5" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 690.814 824.302">
  <defs>
    <style>
      .a00cb6af-c716-4d00-9962-797e598003da,
      .a6fde9f6-9a2f-4715-ac34-678948a4d015,
      .b963f74d-80cb-4571-80bd-9cf5cd28cce2 {
        fill:none;
        stroke-miterlimit:10;
        stroke-width:6px;
      }
      .a6fde9f6-9a2f-4715-ac34-678948a4d015 {
        stroke:url(#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0);
      }
      .b963f74d-80cb-4571-80bd-9cf5cd28cce2 {
        stroke-dasharray:30.322 50.536;
        stroke:url(#a958eb71-8928-4250-a898-e2a9df336375);
      }
      .a00cb6af-c716-4d00-9962-797e598003da {
        stroke:url(#a8cb66bd-35fa-45ad-b9b6-1af210f764d2);
      }
    </style>
    <linearGradient id="bef7cd12-3404-46dc-ac0f-c9d91ddd83d0" x1="60.835" y1="123.864" x2="751.668" y2="123.864" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#ec6608"/>
      <stop offset="0.494" stop-color="#c33089"/>
      <stop offset="1" stop-color="#662483"/>
    </linearGradient>
    <linearGradient id="a958eb71-8928-4250-a898-e2a9df336375" x1="60.835" y1="541.828" x2="751.668" y2="541.828" xlink:href="#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0"/>
    <linearGradient id="a8cb66bd-35fa-45ad-b9b6-1af210f764d2" x1="60.835" y1="932.54" x2="751.668" y2="932.54" xlink:href="#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0"/>
  </defs>
  <path class="a6fde9f6-9a2f-4715-ac34-678948a4d015" d="M748.213,116.426c.215,4.461.381,9.478.436,14.992" transform="translate(-60.835 -116.281)"/>
  <path id="pathRecrut" class="b963f74d-80cb-4571-80bd-9cf5cd28cce2" d="M745.947,181.853c-3.573,34.83-7.4,65.457-20.713,85.466-36.276,54.511-150.309,41.2-247.4,29.872-73.484-8.575-74.824-17.343-139.4-21.446-87.16-5.538-141.016-8.96-191.49,24.51-48.083,31.886-87.4,93.472-82.723,159.319.847,11.934,4.189,59.01,39.83,91.915,35.144,32.448,81.33,32.315,131.744,32.171,53.366-.154,56.932-10.359,130.213-18.383,52.244-5.721,100.335-10.606,160.085,1.532,36.964,7.508,74.081,20.657,109.532,43.659,26.491,17.189,49.773,32.776,59.745,62.809,1.48,4.457,13.436,42.337-6.894,72.766-14.348,21.475-39.623,31.524-81.957,36.766-67.779,8.391-105.681-4.654-182.3-16.086-41.6-6.206-132.521-17.593-227.49-.766-22.971,4.071-60.931,12.4-91.149,42.894-7.9,7.968-23.347,23.951-29.872,49.787a99.225,99.225,0,0,0-1.1,42.916" transform="translate(-60.835 -116.281)"/>
  <path class="a00cb6af-c716-4d00-9962-797e598003da" d="M81.983,925.674a117,117,0,0,0,6.74,13.39" transform="translate(-60.835 -116.281)"/>
</svg>

см. На коде: https://codepen.io/Unrillaz/pen/ZdeezN

Я не понимаю, почему эта линия сплошная, когда я ее оживляю.

Я хочу такую ​​же анимацию. Строка, которая заполняет себя, когда вы прокручиваете вниз, но я хочу, чтобы она была пунктирной Как вы думаете, это возможно?

1 Ответ

3 голосов
/ 21 июня 2019

Стандартная техника «рисования линий» использует изменяющуюся длину черты для имитации эффекта рисования.Очевидно, что если у вашей линии уже есть пунктирный паттерн, эта техника не сработает.По крайней мере, напрямую.

Лучшее решение для этого - применить <mask> к пунктирной линии.Маска состоит из линии, которая покрывает вашу оригинальную (пунктирную).Затем мы используем стандартную технику рисования линий для анимации версии линии в маске.Таким образом, медленно разоблачая / раскрывая оригинальную пунктирную линию.

// Get a reference to the <path>
var path = document.querySelector('#pathRecrut');

// Get length of path... ~577px in this case
var pathLength = path.getTotalLength();

// Make very long dashes (the length of the path itself)
path.style.strokeDasharray = pathLength + ' ' + pathLength;

// Offset the dashes so the it appears hidden entirely
path.style.strokeDashoffset = pathLength;

// When the page scrolls...
window.addEventListener("scroll", function(e) {
 
  // What % down is it? 
  // /2191860/kross-brauzernyi-metod-dlya-opredeleniya-protsenta-vertikalnoi-prokrutki-v-javascript#2191868
  // Had to try three or four differnet methods here. Kind of a cross-browser nightmare.
  var scrollPercentage = (document.documentElement.scrollTop + document.body.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
    
  // Length to offset the dashes
  var drawLength = pathLength * scrollPercentage;
  
  // Draw in reverse
  path.style.strokeDashoffset = pathLength - drawLength;
  
});
<svg id="bf7de8ba-cf75-48ab-a36c-06f8d86635d5" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 690.814 824.302">
  <defs>
    <style>
      .a00cb6af-c716-4d00-9962-797e598003da,
      .a6fde9f6-9a2f-4715-ac34-678948a4d015,
      .b963f74d-80cb-4571-80bd-9cf5cd28cce2 {
        fill:none;
        stroke-miterlimit:10;
        stroke-width:6px;
      }
      .a6fde9f6-9a2f-4715-ac34-678948a4d015 {
        stroke:url(#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0);
      }
      .b963f74d-80cb-4571-80bd-9cf5cd28cce2 {
        stroke-dasharray:30.322 50.536;
        stroke:url(#a958eb71-8928-4250-a898-e2a9df336375);
      }
      .a00cb6af-c716-4d00-9962-797e598003da {
        stroke:url(#a8cb66bd-35fa-45ad-b9b6-1af210f764d2);
      }
    </style>
    <linearGradient id="bef7cd12-3404-46dc-ac0f-c9d91ddd83d0" x1="60.835" y1="123.864" x2="751.668" y2="123.864" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#ec6608"/>
      <stop offset="0.494" stop-color="#c33089"/>
      <stop offset="1" stop-color="#662483"/>
    </linearGradient>
    <linearGradient id="a958eb71-8928-4250-a898-e2a9df336375" x1="60.835" y1="541.828" x2="751.668" y2="541.828" xlink:href="#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0"/>
    <linearGradient id="a8cb66bd-35fa-45ad-b9b6-1af210f764d2" x1="60.835" y1="932.54" x2="751.668" y2="932.54" xlink:href="#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0"/>
    
    <mask id="linemask">
      <path id="pathRecrut" fill="none" stroke="white" stroke-width="10" d="M745.947,181.853c-3.573,34.83-7.4,65.457-20.713,85.466-36.276,54.511-150.309,41.2-247.4,29.872-73.484-8.575-74.824-17.343-139.4-21.446-87.16-5.538-141.016-8.96-191.49,24.51-48.083,31.886-87.4,93.472-82.723,159.319.847,11.934,4.189,59.01,39.83,91.915,35.144,32.448,81.33,32.315,131.744,32.171,53.366-.154,56.932-10.359,130.213-18.383,52.244-5.721,100.335-10.606,160.085,1.532,36.964,7.508,74.081,20.657,109.532,43.659,26.491,17.189,49.773,32.776,59.745,62.809,1.48,4.457,13.436,42.337-6.894,72.766-14.348,21.475-39.623,31.524-81.957,36.766-67.779,8.391-105.681-4.654-182.3-16.086-41.6-6.206-132.521-17.593-227.49-.766-22.971,4.071-60.931,12.4-91.149,42.894-7.9,7.968-23.347,23.951-29.872,49.787a99.225,99.225,0,0,0-1.1,42.916"/>
    </mask>
  </defs>
  <path class="a6fde9f6-9a2f-4715-ac34-678948a4d015" d="M748.213,116.426c.215,4.461.381,9.478.436,14.992" transform="translate(-60.835 -116.281)"/>
  <path class="b963f74d-80cb-4571-80bd-9cf5cd28cce2" d="M745.947,181.853c-3.573,34.83-7.4,65.457-20.713,85.466-36.276,54.511-150.309,41.2-247.4,29.872-73.484-8.575-74.824-17.343-139.4-21.446-87.16-5.538-141.016-8.96-191.49,24.51-48.083,31.886-87.4,93.472-82.723,159.319.847,11.934,4.189,59.01,39.83,91.915,35.144,32.448,81.33,32.315,131.744,32.171,53.366-.154,56.932-10.359,130.213-18.383,52.244-5.721,100.335-10.606,160.085,1.532,36.964,7.508,74.081,20.657,109.532,43.659,26.491,17.189,49.773,32.776,59.745,62.809,1.48,4.457,13.436,42.337-6.894,72.766-14.348,21.475-39.623,31.524-81.957,36.766-67.779,8.391-105.681-4.654-182.3-16.086-41.6-6.206-132.521-17.593-227.49-.766-22.971,4.071-60.931,12.4-91.149,42.894-7.9,7.968-23.347,23.951-29.872,49.787a99.225,99.225,0,0,0-1.1,42.916" transform="translate(-60.835 -116.281)" mask="url(#linemask)"/>
  <path class="a00cb6af-c716-4d00-9962-797e598003da" d="M81.983,925.674a117,117,0,0,0,6.74,13.39" transform="translate(-60.835 -116.281)"/>
</svg>
...