Образцы рисунков динамически загружаются неправильно в Safari - PullRequest
0 голосов
/ 04 мая 2018

Ниже представлен скрипт для изменения изображения при нажатии, изменения будут затронуты на холсте.

Скрипт работает правильно в Firefox и Chrome, но не в Safari

В чем может быть причина?

<script>
  $(function() {

    var house = document.getElementById("house");
    var ctxHouse = house.getContext("2d");
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    var canvas2 = document.getElementById("canvas2");
    var ctxHand = canvas2.getContext("2d");
    var FabricLink;
    var imageObj = new Image();
    var red = new Image();
    red.onload = function() {
      canvas.width = red.width;
      canvas.height = red.height;

      var houseImage = new Image();
      houseImage.onload = function() {
        house.width = houseImage.width;
        house.height = houseImage.height;
        ctxHouse.drawImage(houseImage, 0, 0);
      }
      houseImage.src = "images/img.jpg";

      ctx.drawImage(red, 0, 0);


      imageObj.onload = function() {
        var pattern = ctx.createPattern(imageObj, 'repeat');
        ctx.globalCompositeOperation = 'source-in';
        ctx.rect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = pattern;
        ctx.fill();
      };
      $(imageObj).attr('src', 'images/' + FabricLink + '.png');
    }
    red.src = "images/img.png";
    var imageObj2 = new Image();
    var blue = new Image();
    blue.onload = function() {
      canvas2.width = blue.width;
      canvas2.height = blue.height;

      var houseImage = new Image();
      houseImage.onload = function() {
        house.width = houseImage.width;
        house.height = houseImage.height;
        ctxHouse.drawImage(houseImage, 0, 0);
      }
      houseImage.src = "images/img.jpg";

      ctxHand.drawImage(blue, 0, 0);


      imageObj2.onload = function() {
        var pattern = ctx.createPattern(imageObj2, 'repeat');
        ctxHand.globalCompositeOperation = 'source-in';
        ctxHand.rect(0, 0, canvas2.width, canvas2.height);
        ctxHand.fillStyle = pattern;
        ctxHand.fill();
      };
      $(imageObj2).attr('src', 'images/' + FabricLink + '.png');
    }
    blue.src = "images/img.png";




    $('#style li').click(
      function() {
        //we get our current filename and use it for the src
        var linkIndex = $(this).attr("data-filename");
        $(red).attr('src', 'images/' + linkIndex + '.png');
      }
    );

    $('#Sleeves li').click(
      function() {
        $("#canvas2").addClass("show-z");
        //we get our current filename and use it for the src
        var SleevesLink = $(this).attr("data-filename");
        $(blue).attr('src', 'images/' + SleevesLink + '.png');
      }
    );

    $('#Fabric li').click(
      function() {
        //we get our current filename and use it for the src
        FabricLink = $(this).attr("data-filename");
        $(imageObj2).attr('src', 'images/' + FabricLink + '.png');
        $(imageObj).attr('src', 'images/' + FabricLink + '.png');


      }
    );

    $("#Fabric li:first-child").click();




  }); // end $(function(){});
</script>

Во время отладки мы могли видеть, что imageObj.onload не срабатывает при первом клике, только при обновлении изменение происходит в Safari.

jsfiddle.net / qvfx3kz7 (В скрипте образы не загружаются, но добавлен полный код)

1 Ответ

0 голосов
/ 07 мая 2018

Я не уверен, в чем именно проблема с Safari, но я вижу, что вы слишком усложняете все, пытаясь загрузить свои активы только по запросу, что приводит к тому кошмару обратного вызова, который вы настроили.

Вместо этого подготовьте свои активы, чтобы вы могли загрузить их только один раз. Поскольку вы используете шаблоны, я предполагаю, что каждый шаблон на самом деле является маленьким изображением.
Поэтому вместо загрузки каждого маленького изображения шаблона загрузите один спрайт-лист , который будет содержать всех ваших шаблонов .
Оттуда вы сможете динамически генерировать CanvasPattern синхронно, без необходимости загружать обратный вызов. Чтобы сделать это, вам нужно будет использовать второй, вне экрана, холст, который вы будете использовать как источник createPattern() метода:

// really dummy implementation...
function AssetsLoader() {}
AssetsLoader.prototype = Object.create({
  addImage: function(objs, cb) {
    if (!objs || typeof objs !== 'object') return;
    if (!Array.isArray(objs)) objs = [];
    var toLoad = objs.length,
      imgs = objs.map(loadImage, this);

    function loadImage(obj) {
      if (!obj.src) return;
      this.toLoad++;
      var img = new Image();
      img.src = obj.src;
      img.onload = onimgload;
      img.onerror = onimgerror;
      return obj.img = img;
    }

    function onimgload(evt) {
      if (--toLoad <= 0 && typeof cb === 'function') cb(imgs);
    }

    function onimgerror(evt) {
      console.warn('failed to load image at ', evt.target.src);
    }
  }
});
// Some info about our assets, there are an infinity of ways to deal with it,
// You would have to determine yourself what's best for your own case
var dests = {
  sofa: {
    name: 'sofa',
    src: 'https://i.stack.imgur.com/ryO42.png'
  },
  shirt: {
    name: 'shirt',
    src: 'https://i.stack.imgur.com/cPNbe.png'
  }
};
var patterns = {
  name: 'patterns',
  src: 'https://i.stack.imgur.com/TdIAJ.png',
  positions: {
    orange: {
      x: 0,
      y: 0,
      width: 173,
      height: 173,
      out_width: 75,
      out_height: 75
    },
    violet: {
      x: 173,
      y: 0,
      width: 173,
      height: 173,
      out_width: 35,
      out_height: 35
    },
    psyche: {
      x: 0,
      y: 173,
      width: 173,
      height: 173,
      out_width: 25,
      out_height: 25
    },
    pink: {
      x: 173,
      y: 173,
      width: 173,
      height: 173,
      out_width: 125,
      out_height: 125
    }
  }
}

var assets = new AssetsLoader();
// first load all our images, and only then, start the whole thing
assets.addImage([dests.shirt, dests.sofa, patterns], init);


function init() {
  // populate our selects
  for (var key in dests) {
    dest_select.appendChild(new Option(key, key));
  }
  for (var key in patterns.positions) {
    pat_select.appendChild(new Option(key, key));
  }
  dest_select.onchange = pat_select.onchange = draw;

  var ctx = canvas.getContext('2d');
  var offscreenCtx = document.createElement('canvas').getContext('2d');

  draw();

  function draw() {
    var dest = dests[dest_select.value].img;
    ctx.canvas.width = dest.width;
    ctx.canvas.height = dest.height;

    ctx.globalCompositeOperation = 'source-over';
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(dest, 0, 0, canvas.width, canvas.height);
    ctx.globalCompositeOperation = 'source-in';

    // here we generate the CanvasPattern
    ctx.fillStyle = getPattern(pat_select.value);
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    ctx.globalCompositeOperation = 'luminosity';
    ctx.drawImage(dest, 0, 0, canvas.width, canvas.height);
  }
  // now that we have our patterns loaded in a single sprite-sheet,
  // we can generate the CanvasPatterns synchronously
  function getPattern(key) {
    var pos = patterns.positions[key]; // get our pattern's position in our dictionary
    // resize the offscreen canvas so it matches our pattern
    offscreenCtx.canvas.width = pos.out_width;
    offscreenCtx.canvas.height = pos.out_height;
    offscreenCtx.drawImage(patterns.img, pos.x, pos.y, pos.width, pos.height, 0, 0, pos.out_width, pos.out_height);
    return offscreenCtx.createPattern(offscreenCtx.canvas, 'repeat');
  }
}
<select id="dest_select"></select>
<select id="pat_select"></select>
<br><br><br>
<canvas id="canvas"></canvas>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...