1

I have made a simple p5.js sketch for a site I am building and some of the functions are not working on safari/ios safari, however it all works fine on chrome. There are no errors in the console.

The functions 'showAbout' and 'hideAbout' work fine on safari, but the function 'mousePressed' is not, as well as everything in the draw function. Wondering if there are any errors in my code or if this is a safari glitch?

I will paste my code below.

var dogs = [];
var index;
var x;
var y;
var angle;
var about;
var button;
var canvas;
var exit;
var toggle = false;
var w = window.innerWidth;
var h = window.innerHeight;

function preload() {
  for(let i=0; i<11; i++) {       
      dogs[i] = loadImage(`Images/Batch/dog${i}.jpg`);
  }
  about = select('.about-container');
  about.style('display', 'none');
  }

function setup() {
  canvas = createCanvas(w, h);
  frameRate(5); 
  angleMode(DEGREES);
  button = select('.about-button-text');
  button.mousePressed(showAbout);
  exit = select('.exit');
  exit.mousePressed(hideAbout); 
}

function draw() {
  fill(255);
  textSize(25);
  angle = random(-45,45);
  rotate(angle);
  index = random(dogs);
  index.width = w/3;
  x = random(w);
  y = random(h);
  image(index, x, y);
  
}

function mousePressed() {
  

  if (toggle) {
      noLoop();
      toggle = false;
      
  } else {
      loop();
      toggle = true;
  
  }
}

function showAbout() {
  about.show();
}

function hideAbout() {
  about.hide();
}


function windowResized() {
  resizeCanvas(w, h);
}


  • Your code depends on specific HTML elements existing. You need to provided your HTML code as well for this to be reproducible. Please see https://stackoverflow.com/questions/67410651/how-do-i-include-a-runnable-p5-js-sketch-in-a-stackoverflow-question and https://stackoverflow.com/help/minimal-reproducible-example – Paul Wheeler Jun 04 '21 at 20:07

1 Answers1

1

It's hard to be 100% certain without a reproducible example but it would appear that assigning the width property of a p5.Image object causes images not to display on Safari (no errors, works fine on Chrome). Generally speaking you should not assign values to the fields of p5.js objects. I don't see anything in the documentation suggesting this would be supported. Instead what you probably want to do is specify dimensions in your call to the image() function:

// I've also taken the liberty of making the variables used here local
// to this function instead of being declared globally.
function draw() {
  fill(255);
  textSize(25);
  let angle = random(-45,45);
  rotate(angle);
  let img = random(dogs);
  // ***** This is broken in Safari, and not supported in general:
  // img.width =  w / 3;
  let x = random(w);
  let y = random(h);
  
  let aspect = img.height / img.width;
  
  // image(img, x, y);
  // ***** Instead of changing the width property of the p5.Image object you
  // should be specifying the width and height parameters of the image()
  // function:
  image(img, x, y, w / 3, (w / 3) * aspect);
}

Runnable example:

const imageUrls = [
  'https://cdn.glitch.com/0e291b8c-6059-4ca6-a0ae-84e67e1f94e7%2Forange-fish.jpg?v=1613865086898',
  'https://cdn.glitch.com/0e291b8c-6059-4ca6-a0ae-84e67e1f94e7%2Fblue-fish.jpg?v=1613865087591',
  'https://cdn.glitch.com/0e291b8c-6059-4ca6-a0ae-84e67e1f94e7%2Fgreen-fish.jpg?v=1613865088114',
  'https://cdn.glitch.com/0e291b8c-6059-4ca6-a0ae-84e67e1f94e7%2Fpurple-fish.jpg?v=1613865090105',
  'https://cdn.glitch.com/0e291b8c-6059-4ca6-a0ae-84e67e1f94e7%2Fwhite-fish.jpg?v=1613865093930',
  'https://cdn.glitch.com/0e291b8c-6059-4ca6-a0ae-84e67e1f94e7%2Fblack-fish.jpg?v=1613983100022',
  'https://cdn.glitch.com/0e291b8c-6059-4ca6-a0ae-84e67e1f94e7%2Fred-fish.png?v=1613983604942'
];

var dogs = [];
var about;
var button;
var canvas;
var exit;
var toggle = true;
var w = window.innerWidth;
var h = window.innerHeight;

function preload() {
  for(let i=0; i<imageUrls.length; i++) {
    let url = imageUrls[i];
    dogs[i] = loadImage(imageUrls[i]);
  }
  about = select('.about-container');
  about.style('display', 'none');
}

function setup() {
  canvas = createCanvas(w, h);
  frameRate(5); 
  angleMode(DEGREES);
  button = select('.about-button-text');
  button.mousePressed(showAbout);
  exit = select('.exit');
  exit.mousePressed(hideAbout); 
}

function draw() {
  fill(255);
  textSize(25);
  let angle = random(-45,45);
  rotate(angle);
  let img = random(dogs);
  //img.width = w/3;
  let x = random(w);
  let y = random(h);
  
  let aspect = img.height / img.width;
  
  //image(img, x, y);
  image(img, x, y, w / 3, (w / 3) * aspect);
}

function mousePressed() {
  if (toggle) {
    print('toggle off');
    noLoop();
    toggle = false;
  } else {
    print('toggle on');
    loop();
    toggle = true;
  }
}

function showAbout() {
  about.show();
}

function hideAbout() {
  about.hide();
}

function windowResized() {
  print(`Resize ${w} x ${h}`);
  resizeCanvas(w, h);
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script>
    <meta charset="utf-8" />

  </head>
  <body>
    <button class="about-button-text">Show About</button>
    <div class="about-container">
      <p>About info...</p>
      <button class="exit">Exit</button>
    </div>
  </body>
</html>

Update: A version of the snippet that starts displaying images as soon as any are availalbe

const imageUrls = [
  'https://cdn.glitch.com/0e291b8c-6059-4ca6-a0ae-84e67e1f94e7%2Forange-fish.jpg?v=1613865086898',
  'https://cdn.glitch.com/0e291b8c-6059-4ca6-a0ae-84e67e1f94e7%2Fblue-fish.jpg?v=1613865087591',
  'https://cdn.glitch.com/0e291b8c-6059-4ca6-a0ae-84e67e1f94e7%2Fgreen-fish.jpg?v=1613865088114',
  'https://cdn.glitch.com/0e291b8c-6059-4ca6-a0ae-84e67e1f94e7%2Fpurple-fish.jpg?v=1613865090105',
  'https://cdn.glitch.com/0e291b8c-6059-4ca6-a0ae-84e67e1f94e7%2Fwhite-fish.jpg?v=1613865093930',
  'https://cdn.glitch.com/0e291b8c-6059-4ca6-a0ae-84e67e1f94e7%2Fblack-fish.jpg?v=1613983100022',
  'https://cdn.glitch.com/0e291b8c-6059-4ca6-a0ae-84e67e1f94e7%2Fred-fish.png?v=1613983604942'
];

var dogs = [];
var about;
var button;
var canvas;
var exit;
var toggle = true;
var w = window.innerWidth;
var h = window.innerHeight;

function setup() {
  canvas = createCanvas(w, h);
  frameRate(5);
  angleMode(DEGREES);

  for (let i = 0; i < imageUrls.length; i++) {
    loadImage(imageUrls[i], img => dogs.push(img));
  }

  about = select('.about-container');
  about.style('display', 'none');
  button = select('.about-button-text');
  button.mousePressed(showAbout);
  exit = select('.exit');
  exit.mousePressed(hideAbout);
}

function draw() {
  fill(255);
  textSize(25);
  let angle = random(-45, 45);
  rotate(angle);
  if (dogs.length > 0) {
    let img = random(dogs);
    //img.width = w/3;
    let x = random(w);
    let y = random(h);

    let aspect = img.height / img.width;

    //image(img, x, y);
    image(img, x, y, w / 3, (w / 3) * aspect);
  }
}

function mousePressed() {
  if (toggle) {
    print('toggle off');
    noLoop();
    toggle = false;
  } else {
    print('toggle on');
    loop();
    toggle = true;
  }
}

function showAbout() {
  about.show();
}

function hideAbout() {
  about.hide();
}

function windowResized() {
  print(`Resize ${w} x ${h}`);
  resizeCanvas(w, h);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script>
  <meta charset="utf-8" />

</head>

<body>
  <button class="about-button-text">Show About</button>
  <div class="about-container">
    <p>About info...</p>
    <button class="exit">Exit</button>
  </div>
</body>

</html>
Paul Wheeler
  • 18,988
  • 3
  • 28
  • 41
  • Hi Paul, Thank you for this! It seems to be working on Safari now. The only issue I am finding is that it takes a while for the images to begin appearing on initial page load - do you know what could be causing this or a way to make them start appearing immediately on page load? – Lily Weinbrand Jun 09 '21 at 16:29
  • In my snippet I load all the images in the `preload()` function. Any load operations started here will delay the initialization of the sketch until all of those resources are finished loading (you should see the text "Loading.." where the sketch will be). If you prefer you can load your images in the `setup()` function and as each image is loaded you can add it to the list of available images (the `loadImage()` function takes a second argument which is a callback function that is invoked when loading is complete). – Paul Wheeler Jun 09 '21 at 20:30
  • Thank you Paul. Would it be a simple case of just moving this code to the setup() function, including the for loop? Would you be able to give an example of how this would be written as I don't quite understand what you mean by the callback function for loadImage() – Lily Weinbrand Jun 15 '21 at 16:16
  • @LilyWeinbrand take a look at the second hidden code snippet in my answer, it calls loadImage() in the setup() function and uses the callback to add each image to the "dogs" array. Note I'm using an https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions for the callback. – Paul Wheeler Jun 15 '21 at 19:08
  • @LilyWeinbrand Yeah, that is happening because the "about-container" div is displayed briefly before `setup()` runs. To fix this you can add `style="display: none"` to the HTML element – Paul Wheeler Jun 17 '21 at 19:31
  • Hi Paul, thanks yeah I sorted this. I'm still having problems with safari for ios, the images are now displaying but the page is scrolling longer than window width, cutting the background image off and on the 'about' page cutting the text off. The home page should be the size of the window with no scroll, and the about page has a scroll but a black background that hides the background image of the dog when it is displayed. – Lily Weinbrand Jun 22 '21 at 17:38
  • I don't know much about p5.js issues related to iOS Safari. You should post a new question. – Paul Wheeler Jun 23 '21 at 00:41