如何使用JavaScript定时器随机更改HTML元素——跨越网络,而不仅仅是在浏览器内部?

3

我正在使用HTML、CSS和JavaScript创建一个网站,其中包括一些元素,其中包括一个图片元素。

我的目标是每小时随机更换这张图片。在浏览器中运行时,我能够完美地完成这个功能。

我的问题是:如何随机更改所有用户所看到的同一个元素(整个互联网)?

按照我目前的写法,它只在浏览器内运行随机图片函数,并在刷新页面时重置。

我目前正在使用setInterval()并不断检查时间是否符合date.getMinutes() === 0,然后我认为已经过了一个小时,我调用一个changePicHourly()函数。

我没有问题使其正常工作。然而,很明显,每个访问者都会看到不同的图片。我不想要那样,我想要跨越时间和空间的一致性! 哈哈。

我并不是要求具体的编码说明,我更关注理解概念。如何在全球范围内更改元素?

希望我表述清晰。 谢谢!


7
你需要在服务器上进行操作,这样加载同一URL页面的人会得到相同的内容。 - isherwood
1
你可以使用<meta http-equiv="refresh" content="30"> 来刷新页面。或者你可以通过Websockets连接全球计算机,并发送一个刷新命令。 - ControlAltDel
@isherwood 谢谢!所以这是用 PHP 实现的,我猜测对吗? - MissAri
我不知道你的服务器上有什么。请参见[ask]。你的问题非常广泛。 - isherwood
1
有很多服务器端选项,不只有PHP,但它确实是一个选择。 - Jon P
显示剩余3条评论
2个回答

3

不使用后端的一种实现方法如下:

使用new Date.getTime()来获取协调世界时(UTC)时间,这是所有连接到互联网的计算机都一样的。然后将此毫秒数转换为小时,并创建一个伪随机数以每小时移动图像。

在以下代码中,我仅使用了十个图像,但随机数旨在用于多达100个图像。

const 
  hours = Math.round(new Date().getTime()/(1000*60*60)),
  numbers = [
    Number(hours.toString().slice(0,2)),
    Number(hours.toString().slice(2,4)),
    Number(hours.toString().slice(4,6))
  ],
  images = [
    'https://picsum.photos/id/237/200/300', 
    'https://picsum.photos/id/236/200/300', 
    'https://picsum.photos/id/235/200/300',
    'https://picsum.photos/id/234/200/300',
    'https://picsum.photos/id/233/200/300',
    'https://picsum.photos/id/232/200/300',
    'https://picsum.photos/id/231/200/300',
    'https://picsum.photos/id/230/200/300',
    'https://picsum.photos/id/229/200/300',
    'https://picsum.photos/id/228/200/300'
  ];

function hourlyRand(){
  const pseudoRandString = (numbersArr) => {
    let rand = 1
    numbersArr.forEach((n, i) => {
      if(n !== 0) rand = rand * n 
    })
    return rand.toString()
  }  
  
  // get a pseudo random number and convert to string
  let randString = pseudoRandString(numbers)

  // length of the pseudo random number string
  let L = randString.length

  // slice the string and convert to number
  let n = Number(randString.slice(L-3,L-1))
  
  // return the double digit hourly random number
  return n
}

// pseudo-random number between 0 and 99 
console.log('Hourly pseudo-random number: ' + hourlyRand())

// pseudo-random number between 0 and 9 
let n = Math.round(hourlyRand()/10)

document.getElementById('root').innerHTML = '<img src=' + images[n] + '/>'
<div id="root"/>

如果是我的项目,我会在后端构建逻辑,然后在前端使用API以我想要的方式呈现图像。这将允许所有用户在特定时间点看到相同的更改。

2
这将是一致的,但不是随机的(但也许原帖作者可以接受这种情况)。 - jsejcksn
1
@jsejcksn 谢谢你指出来,我漏掉了。我会相应地进行更新。 - Gass
你需要的是用UTC小时作为输入来导出数组索引的种子PRNG(例如https://github.com/davidbau/seedrandom)。 - jsejcksn
1
@Gass 谢谢!所以澄清一下,如果它是伪随机的,那么这种方法是可行的,但要真正从数组中获取一个随机图片并在全球范围内保持一致,必须在后端完成,这正确吗? - MissAri
从我的角度来看,那将是最好的方式... - Gass
1
如果您使用当前的UTC时间戳作为种子来创建可重复的伪随机数,就像这段代码所做的那样,那么没有理由必须在服务器端执行此操作。这将使得每个客户端浏览器在全球范围内都能看到相同的每小时变化的图像。 - Carsten Massmann

2

以下是一种基于当前UTC小时计算出的种子值的略有不同的伪随机数生成器:

const d = new Date(),
  imgs = [...Array(100)].map((c, i) => 'https://picsum.photos/id/X/200/300'.replace("X", 216 + i));

// define a seed-based random number generator (later: "rand()"), as suggested in
// https://dev59.com/QHRB5IYBdhLWcg3wxZ1K
function sfc32(a, b, c, d) {
  return function() {
    var t = (a + b) | 0;
    a = b ^ b >>> 9;
    b = c + (c << 3) | 0;
    c = (c << 21 | c >>> 11);
    d = d + 1 | 0;
    t = t + d | 0;
    c = c + t | 0;
    return (t >>> 0) / 4294967296;
  }
}
// create a seed, based on the current hour in UTC time:
const seed = Math.round(new Date().getTime() / (1000 * 60 * 60));
// initialise the number generator rand() with this seed:
const rand = sfc32(0x9E3779B9, 0x243F6A88, 0xB7E15162, seed ^ 0xDEADBEEF);
// carry out some initial "mixing" ... 
for (let n = 15; n--;) rand();
// now rand() will deliver a pseudo-random number that will be reproducible for identical seeds.

let src = `<img src="${imgs[Math.floor(rand()*100)]}">`;
document.getElementById("root").innerHTML = `<img src="${imgs[Math.floor(rand()*imgs.length)]}">`;
<div id="root"></div>

在表达式[...Array(100)]中,我将可供选择的图片数量限制为100。当然,您可以在此处使用任意数量的图片。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接