@KseniyaMirosha

Почему по клику на кнопку download нужная картинка загружается только со второго раза?

html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link href="assets/favicon.ico" rel="shortcut icon" />
  <link href="https://fonts.gstatic.com" rel="preconnect" />
  <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;800&display=swap" rel="stylesheet" />
  <link href="style.css" rel="stylesheet" />
  <title>photo-filter</title>
</head>

<body>
  <header class="header">
    <h1 class="header-title">Photo-filter</h1>
  </header>
  <main class="main">
    <div class="filters">
      <label class="container">
        Blur:
        <input class="input blur" name="blur" data-sizing="px" data-name="blur" type="range" min="0" max="10" value="0" />
        <output class="output" name="result">0</output>
      </label>
      <label class="container">
        Invert:
        <input class="input" name="invert" data-sizing="%" data-name="invert" type="range" min="0" max="100" value="0" />
        <output class="output" name="result">0</output>
      </label>
      <label class="container">
        Sepia:
        <input class="input" name="sepia" data-sizing="%" data-name="sepia" type="range" min="0" max="100" value="0" />
        <output class="output" name="result">0</output>
      </label>
      <label class="container">
        Saturate:
        <input class="input saturate" name="saturate" data-name="saturate" data-sizing="%" type="range" min="0" max="200" value="100" />
        <output class="output" id="saturate" name="result">100</output>
      </label>
      <label class="container">
        Hue rotate:
        <input class="input" name="hue" data-name = "hue-rotate" data-sizing="deg" type="range" min="0" max="360" value="0" />
        <output class="output" name="result">0</output>
      </label>
    </div>
    <div class="editor">
      <div class="btn-container">
        <button class="btn btn-reset">Reset</button>
        <button class="btn btn-next btn-active">Next picture</button>
        <label class="btn btn-load" for="btnInput">
          Load picture
          <input class="btn-load--input" id="btnInput" name="upload" type="file" placeholder="Load picture" />
        </label>
        <button class="btn btn-save">Save picture</button>
      </div>
      <div class="img-container">
        <img id="image" src="assets/img/img.jpg" alt="image" />
        <canvas id="canvas"></canvas>
      </div>


    </div>
  </main>
  <footer class="footer">
    <div class="footer-container">
      <a class="github" href="https://github.com/KseniyaMirosha" target="_blank" rel="noopener noreferrer"
        title="Open my github page">Kseniya Lazovskaya</a>
      <a class="rss" href="https://rs.school/js/" target="_blank" rel="noopener noreferrer"
        title="Read about the course">
        <span class="rss-year">'21</span>
      </a>
    </div>
  </footer>
  <button class="fullscreen openfullscreen" onclick="fullscreen();"></button>

  <script defer src="canvas.js"></script>
</body>

</html>


js

// Вешаем обработчик события с делегированием для применения фильтров
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let canvasFilter;
const input = document.querySelector('.filters')
  .addEventListener('input', event => {
    if (event.target.matches("input")) {
      const suffix = event.target.dataset.sizing;
      if (event.target.dataset.name === "blur") {
        filter = event.target.dataset.name + "(" + (event.target.value * 2) + suffix + ")";
      } else {
        filter = event.target.dataset.name + "(" + event.target.value + suffix + ")";
      }
      canvasFilter = filter;
      document.documentElement.style.setProperty(`--${event.target.name}`, event.target.value + suffix);
    }
  });

// Отображаем значение ползунков в output 
const allInputs = document.querySelectorAll(".container");
allInputs.forEach(element => {
  const input = element.querySelector(".input");
  const output = element.querySelector(".output");

  input.addEventListener("input", () => {
    setValue(input, output);
  });
  setValue(input, output);
});

function setValue(input, output) {
  const val = input.value;
  output.innerHTML = val;
}

// Настройки для кнопки reset
const inputs = document.querySelectorAll('input');
const outputs = document.querySelectorAll('output');
let button = document.querySelector('.btn-reset');
button.addEventListener('click', event => {
  if (button.matches(".btn-reset")) {
    inputs.forEach(element => {
      if (element.value) {
        element.value = 0;
        filter = element.name + "(" + element.value + element.sizing + ")";
        canvasFilter = filter;
        document.documentElement.style.setProperty(`--${element.name}`, element.value);
      }
    });
    outputs.forEach(element => {
      element.innerHTML = 0;
    });
    let saturateOutput = document.getElementById("saturate");
    saturateOutput.innerHTML = 100;
    let saturateInput = document.querySelector(".saturate");
    saturateInput.value = 100;
    document.documentElement.style.setProperty(`--saturate`, "100%");
  };
});

// Настройки для кнопки next picture
const base = new Array();
base[0] = 'https://raw.githubusercontent.com/rolling-scopes-school/stage1-tasks/assets/images/night/';
base[1] = 'https://raw.githubusercontent.com/rolling-scopes-school/stage1-tasks/assets/images/morning/';
base[2] = 'https://raw.githubusercontent.com/rolling-scopes-school/stage1-tasks/assets/images/day/';
base[3] = 'https://raw.githubusercontent.com/rolling-scopes-school/stage1-tasks/assets/images/evening/';

const images = ['01.jpg', '02.jpg', '03.jpg', '05.jpg', '06.jpg', '07.jpg', '08.jpg', '09.jpg', '10.jpg', '11.jpg', '12.jpg', '13.jpg', '14.jpg', '15.jpg', '16.jpg', '17.jpg', '18.jpg', '19.jpg', '20.jpg'];
let i = 0;
let x = 0;
let date = new Date();
let j = date.getHours();
const image = document.querySelector('img');
const btn = document.querySelector('.btn-next');

function viewImage(src) {
  const img = new Image();
  img.src = src;
  img.onload = () => {
    image.src = `${src}`;
  };
}

function getImage() {
  i = Math.floor(j / 6);
  const imgIndex = x % images.length;
  const imageSrc = base[i] + images[imgIndex];
  viewImage(imageSrc);
  x++;
  btn.disabled = true;
  setTimeout(function() {
    btn.disabled = false
  }, 1000);
  return imageSrc;
}
btn.addEventListener('click', getImage);

// Настройки для кнопки Load
const fileInput = document.querySelector('input[type="file"]');
const imageContainer = document.querySelector('.img-container');
let currentImg = {};

fileInput.addEventListener('change', function(e) {
  const file = fileInput.files[0];
  const reader = new FileReader();
  reader.onload = () => {
    const img = new Image();
    img.src = reader.result;
    imageContainer.innerHTML = "";
    imageContainer.append(img);
    currentImg.src = img.src;
  }
  reader.readAsDataURL(file);

});

// Настройки для кнопки Save picture

const download = document.querySelector('.btn-save');
let currentImage = image;

function drawImage() {
  const img = new Image();
  img.setAttribute('crossOrigin', 'anonymous');
  if (currentImg.src) {
    console.log(1);
    img.src = currentImg.src;
  } else {
    console.log(2);
    img.src = currentImage.src;
  }

  img.onload = function() {
    canvas.width = img.width;
    canvas.height = img.height;
    const ctx = canvas.getContext("2d");
    ctx.filter = canvasFilter;
    ctx.drawImage(img, 0, 0);
  };
}

download.addEventListener('click', function(e) {
  drawImage();
  console.log(canvas.toDataURL());
  const dataURL = canvas.toDataURL("image/jpeg");
  let link = document.createElement('a');
  link.download = 'download.png';
  link.href = dataURL;
  link.click();
  link.delete;
});


// Функция на полный экран
function fullscreen() {
  let checkFullScreen = (document.fullscreenElement && document.fullscreenElement !== null) ||
    (document.webkitFullscreenElement && document.webkitFullscreenElement !== null);

  let docElement = document.documentElement;
  if (!checkFullScreen) {
    if (docElement.requestFullscreen) {
      docElement.requestFullscreen();
    } else if (docElement.webkitRequestFullScreen) {
      docElement.webkitRequestFullScreen();
    }
  } else {
    if (document.exitFullscreen) {
      document.exitFullscreen();
    } else if (document.webkitExitFullscreen) {
      document.webkitExitFullscreen();
    }
  }
}


Пишу приложение фото-фильтр.

Применяю фильтры через канвас, а когда хочу сохранить, то нужная картинка сохраняется только после второго клика. В чем может быть проблема? На первом клике загружается предыдущее состояние картинки.
  • Вопрос задан
  • 46 просмотров
Пригласить эксперта
Ответы на вопрос 1
Seasle
@Seasle Куратор тега JavaScript
\( ゚ヮ゚)/
Потому что изображение на canvas'е будет готово после загрузки изображения.
Вариант 1 - функция обратного вызова

function drawImage(callback) {
  const img = new Image();
  img.setAttribute('crossOrigin', 'anonymous');
  if (currentImg.src) {
    console.log(1);
    img.src = currentImg.src;
  } else {
    console.log(2);
    img.src = currentImage.src;
  }

  img.onload = function() {
    canvas.width = img.width;
    canvas.height = img.height;
    const ctx = canvas.getContext("2d");
    ctx.filter = canvasFilter;
    ctx.drawImage(img, 0, 0);

    callback();
  };
}

download.addEventListener('click', function(e) {
  drawImage(function () {
    console.log(canvas.toDataURL());
    const dataURL = canvas.toDataURL("image/jpeg");
    let link = document.createElement('a');
    link.download = 'download.png';
    link.href = dataURL;
    link.click();
  });
});


Вариант 2 - promis'ы

function drawImage(callback) {
  return new Promise(function (resolve) {
    const img = new Image();
    img.setAttribute('crossOrigin', 'anonymous');
    if (currentImg.src) {
      console.log(1);
      img.src = currentImg.src;
    } else {
      console.log(2);
      img.src = currentImage.src;
    }

    img.onload = function() {
      canvas.width = img.width;
      canvas.height = img.height;
      const ctx = canvas.getContext("2d");
      ctx.filter = canvasFilter;
      ctx.drawImage(img, 0, 0);

      resolve();
    };
  });
}

download.addEventListener('click', function(e) {
  drawImage().then(function () {
    console.log(canvas.toDataURL());
    const dataURL = canvas.toDataURL("image/jpeg");
    let link = document.createElement('a');
    link.download = 'download.png';
    link.href = dataURL;
    link.click();
  });
});
// или
download.addEventListener('click', async function(e) {
  await drawImage();
  console.log(canvas.toDataURL());
  const dataURL = canvas.toDataURL("image/jpeg");
  let link = document.createElement('a');
  link.download = 'download.png';
  link.href = dataURL;
  link.click();
});

Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы