Svg перестает работать при изменении позиции на странице html

Я использую виджет svg ниже из этого ответа на вопрос Захват подписи с помощью HTML5 и iPad для создания захватываемой подписи. Код как есть работает, но когда я помещаю над ним контент, например текст в теге <p>, он перестает работать, что проблематично, поскольку мне нужно, чтобы он находился внизу документа. Кто-нибудь знает, почему он перестает работать и как заставить его работать независимо от того, где он расположен на html-странице?

//init
let r = document.getElementById('r'),
  p = document.getElementById('p'),
  signaturePath = '',
  isDown = false,
  svg = document.getElementById('sig_panel'),
  b_show = document.getElementById('show'),
  b_clear = document.getElementById('clear'),
  pathdata = document.getElementById('pathdata');

//drawing functions
function isTouchEvent(e) {
  return e.type.match(/^touch/);
}

function getCoords(e) {
  if (isTouchEvent(e)) {
    return e.targetTouches[0].clientX + ',' + e.targetTouches[0].clientY;
  }
  return e.clientX + ',' + e.clientY;
}

function down(e) {
  signaturePath += 'M' + getCoords(e) + ' ';
  p.setAttribute('d', signaturePath);
  isDown = true;

  if (isTouchEvent(e)) e.preventDefault();
}

function move(e) {
  if (isDown) {
    signaturePath += 'L' + getCoords(e) + ' ';
    p.setAttribute('d', signaturePath);
  }

  if (isTouchEvent(e)) e.preventDefault();
}

function up(e) {
  isDown = false;

  if (isTouchEvent(e)) e.preventDefault();
}

//input handlers
r.addEventListener('touchstart', down, false);
r.addEventListener('touchmove', move, false);
r.addEventListener('touchend', up, false);
r.addEventListener('mousedown', down, false);
r.addEventListener('mousemove', move, false);
r.addEventListener('mouseup', up, false);
r.addEventListener('mouseout', up, false);

//helper functions
function clearSignature() {
  pathdata.textContent = '';
  signaturePath = '';
  p.setAttribute('d', '');
}

function getSignature() {
  pathdata.textContent = signaturePath;
  return signaturePath;
}

//button handlers
b_show.addEventListener('click', getSignature);
b_clear.addEventListener('click', clearSignature);
svg {
  margin: .5em;
  border: 1px solid gray;
  border-radius: .5em;
}

.flex {
  display: flex;
}

button {
  margin: .5em;
}

#pathdata {
  font-family: monospace;
  background: #ddd;
  padding: 1em;
  margin: 1em .5em;
}
<svg id = "sig_panel" xmlns = "http://www.w3.org/2000/svg" width = "300" height = "100" viewBox = "0 0 300 100">
  <rect id = "r" width = "300" height = "100" fill = "#ffa"/>
  <line x1 = "0" y1 = "80" x2 = "300" y2 = "80" stroke = "#666" stroke-width = "1" stroke-dasharray = "3" shape-rendering = "crispEdges" pointer-events = "none"/>
  <path id = "p" stroke = "navy" stroke-width = "2" fill = "none" pointer-events = "none"/>
</svg>
<div class = "flex">
  <button id = "show">Show signaure path data</button>
  <button id = "clear">Clear signature</button>
</div>
<div id = "pathdata"></div>
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
0
51
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я не могу сказать вам, как на самом деле решить проблему, но могу предложить возможный обходной путь: если svg работает, когда он закодирован как верхний элемент, то вы можете просто создать свою страницу в обратном порядке, а затем использовать flex column-revere, и svg будет отображаться внизу.

Например: Ниже приведен пример. Для демонстрации я использовал SVG для значка начальной загрузки.

.container {
    display: flex;
    flex-direction: column-reverse;
    
    /*add other flex properties like justify-content to better display everything*/
    }
<div class='container'>
     <svg xmlns = "http://www.w3.org/2000/svg" width = "16" height = "16" fill = "currentColor" class = "bi bi-check-circle-fill" viewBox = "0 0 16 16">
      <path d = "M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0m-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
     </svg>
     <p>Your P element</p>
    </div>

    

Ценю идею, но пока мне не удалось заставить это решение работать. Виджет подписи svg не позволяет мне рисовать подпись в поле даже после помещения в <div class='container'> с обозначенным CSS в тегах стиля заголовка.

gatorreina 10.08.2024 03:21
Ответ принят как подходящий

Вам необходимо преобразовать координаты экрана в пользовательские единицы SVG, как описано здесь «Как преобразовать координаты элемента svg в координаты экрана?»

Теперь вы можете легко масштабировать свой SVG, не испортив координаты. По сути, вам нужно только обновить функцию getCoords(e).

//init
let r = document.getElementById('r'),
  p = document.getElementById('p'),
  signaturePath = '',
  isDown = false,
  svg = document.getElementById('sig_panel'),
  b_show = document.getElementById('show'),
  b_clear = document.getElementById('clear'),
  pathdata = document.getElementById('pathdata');


//drawing functions
function isTouchEvent(e) {
  return e.type.match(/^touch/);
}

function getCoords(e) {
  let pt

  if (isTouchEvent(e)) {
    pt = new DOMPoint(e.targetTouches[0].clientX, e.targetTouches[0].clientY);

  } else {
    pt = new DOMPoint(e.clientX, e.clientY);
  }

  // get Svg transform matrix
  let ctm = svg.getScreenCTM().inverse();

  // convert screen to SVG coordinates
  pt = pt.matrixTransform(ctm);

  // round coordinates   
  let decimals = 1;
  return `${+pt.x.toFixed(decimals)} ${+pt.y.toFixed(decimals)}`;
}

function down(e) {
  signaturePath += 'M' + getCoords(e) + ' ';
  p.setAttribute('d', signaturePath);
  isDown = true;

  if (isTouchEvent(e)) e.preventDefault();
}

function move(e) {
  if (isDown) {
    signaturePath += getCoords(e) + ' ';
    p.setAttribute('d', signaturePath);
  }

  if (isTouchEvent(e)) e.preventDefault();
}

function up(e) {
  isDown = false;

  if (isTouchEvent(e)) e.preventDefault();
}

//input handlers
r.addEventListener('touchstart', down, false);
r.addEventListener('touchmove', move, false);
r.addEventListener('touchend', up, false);
r.addEventListener('mousedown', down, false);
r.addEventListener('mousemove', move, false);
r.addEventListener('mouseup', up, false);
r.addEventListener('mouseout', up, false);

//button handlers
b_show.addEventListener('click', getSignature);
b_clear.addEventListener('click', clearSignature);

//helper functions
function clearSignature() {
  pathdata.textContent = '';
  signaturePath = '';
  p.setAttribute('d', '');
}

function getSignature() {
  pathdata.textContent = signaturePath;
  return signaturePath;
}
svg {
  margin: .5em;
  border: 1px solid gray;
  border-radius: .5em;
}

.flex {
  display: flex;
}

button {
  margin: .5em;
}

#pathdata {
  font-family: monospace;
  background: #ddd;
  padding: 1em;
  margin: 1em .5em;
}
<svg id = "sig_panel" viewBox = "0 0 300 100">
  <rect id = "r" width = "100%" height = "100%" fill = "#ffa"/>
  <line x1 = "0" y1 = "80" x2 = "300" y2 = "80" stroke = "#666" stroke-width = "1" stroke-dasharray = "3" shape-rendering = "crispEdges" pointer-events = "none" />
  <path id = "p" stroke = "navy" stroke-width = "2" fill = "none" pointer-events = "none"/>
</svg>
<div class = "flex">
  <button id = "show">Show signaure path data</button>
  <button id = "clear">Clear signature</button>
</div>
<div id = "pathdata"></div>

КСТАТИ. вы также можете сэкономить несколько байтов, опустив командные буквы L и применив некоторое округление координат.

Вы также можете поиграть с некоторыми методами сглаживания кривой упрощения, как описано здесь «Гладкое рисование от руки в формате SVG»

Другие вопросы по теме