纽约时报悼念新冠去世患者页面是怎么做出来的?

起因是高中同学发微博感叹这个网站的交互做得很漂亮,本能地就去看了一下。这是纽约时报悼念因新冠去世的人的一个页面,确实很漂亮,大家可以先去看看(需要fq)Remembering the Nearly 100,000 Lives Lost to Coronavirus in America - The New York Times

下面我们来分析一下这些效果是怎么做出来的。

One hundred thousand统计

纽约时报悼念新冠去世患者页面是怎么做出来的?_第1张图片
页面里每隔一段距离就会讲述一下关于十万的一些意义,这个其实比较简单,看html对应的代码。

<div id="g-total">
	<div class="g-slide g-header">
		<header id="g-interactive-header" style="transform: translate(-50%, -1728.13px);">
			<h1 id="g-interactive-heading" class="interactive-heading" itemprop="headline">An Incalculable Lossh1>
			
			<p id="g-interactive-leadin" class="interactive-leadin">America is fast approaching a grim milestone in the coronavirus outbreak — each figure here represents one of the nearly 100,000 lives lost so far. But a count reveals only so much. Memories, gathered from obituaries across the country, help us to reckon with what was lost.p>
			<div class="g-interactive-byline">
				<span class="g-byline" itemprop="name">By The New York Timesspan>
				<time id="interactive-timestamp" class="interactive-timestamp" datetime="2020-05-24">May 24, 2020time>
			div>
		header>
	div>

	
		<div class="g-slide">
			<div class="g-slide-inner">
				
					<p>One hundred thousand.p>
				
					<p>Toward the end of May in the year 2020, the number of people in the United States who have died from the coronavirus neared 100,000 — almost all of them within a three-month span. An average of more than 1,100 deaths a day.p>
				
			div>
		div>

		<div class="g-slide g-spacer">div>
	
		<div class="g-slide">
			<div class="g-slide-inner">
				
					<p>One hundred thousand.p>
				
					<p>A number is an imperfect measure when applied to the human condition. A number provides an answer to how many, but it can never convey the individual arcs of life, the 100,000 ways of greeting the morning and saying good night.p>
				
			div>
		div>
		
		…………………………(此处省略若干行代码)
		
		<div class="g-slide g-spacer">div>
div>

大家看其中一部分就好了。这里其实就是显式地写出来的,用了一定的CSS样式,打一段话,用一个g-spacer隔开,对应的CSS可以在这一段上方给的连接里找到,来看一下相关的:

.g-slide {
  height: 100vh;
  pointer-events: none;
  position: relative;
}
.g-slide.g-spacer {
  height: 300vh;
}
@media all and (min-width: 740px) {
  .g-slide.g-spacer {
    height: 200vh;
  }
}
.g-slide .g-slide-inner {
  background: white;
  box-sizing: border-box;
  border-radius: 4px;
  left: 50%;
  max-width: 680px;
  padding: 15px;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 30px);
}

一个个小人的生平

纽约时报悼念新冠去世患者页面是怎么做出来的?_第2张图片
页面上给了很多小人的信息,让你确切地感受到这些逝去的生命都曾是那样鲜活,他们离我们很近。这是怎么做到的呢?
其实分析代码,发现还是挺暴力的(笑)。当然纽约时报不担心这些数据被恶意盗取做什么坏事,所以也没有费劲写什么反爬虫的。
来看对应的html部分:

<div id="g-0" class="g-obit g-init" data-date="February 6" style="width: 320px; transform: translate(292.725px, 526.342px);">
				<div class="g-obit-inner">
					<b>Auditor in Silicon Valley.b>
					<i>Patricia Dowd, 57, San Jose, Calif.i>
				div>
			div>
………………此处省略代码若干
<div id="g-1000" class="g-obit g-init" data-date="May 19" style="width: 320px; transform: translate(642.249px, 240929px);">
				<div class="g-obit-inner">
					<b>Champion of people with speech disorders.b>
					<i>Annie Glenn, 100, St. Paul, Minn.i>
				div>
			div>

所以程序员就这样将1001个人的小信息这样显式地写出来了。对应的CSS代码如下:

#g-obits .g-obit .g-obit-inner {
  opacity: 0;
  visibility: hidden;
  max-width: 320px;
  position: absolute;
  top: 50%;
  transform: translate(0, -55%);
}
#g-obits .g-obit.g-init .g-obit-inner {
  opacity: 1;
  visibility: visible;
}

在html里面设置了transform: translate的值,所以就覆盖了,将这些文字固定在页面的一个位置上。

日期和累计死亡人数

纽约时报悼念新冠去世患者页面是怎么做出来的?_第3张图片
比较复杂的是这个地方。随着滚动条向下拉,日期会不断增加,随之显示当天的累计死亡人数。
对应的html其实很简单:

<div class="g-date g-show">
	<div id="g-day">March 30div>
	<div id="g-count">Deaths: 3,356div>
div>

当然对应的CSS里面会设置样式,我们就不看了。重点来看看JS里面有什么东西。
JS在这一坨的最后,还很贴心地写了注释

<!-- JS generated from src/script.js -->
<script id="nytg-rendered-js" src="https://static01.nyt.com/newsgraphics/2020/05/18/usobits/c932bd49b3babd39ed429d9d4a7d49f68f7e59b8/build.js"></script>

所以我们顺着链接打开看看。
首先注意到的是它把这两个元素给连接出来了,因此这个文档里修改display_day和display_count的值,就可以修改日期和累计死亡人数的值了。

var display_day = document.getElementById('g-day');
var display_count = document.getElementById('g-count');

在哪里被修改了呢?我们找到了这个update函数:

function update(){
	updating = true;
	scrollY = scrollY + ((newScrollY - scrollY) / 4);
	// var pct = scrollY / height
	var y = scrollY * speed;

	render(y);

	htmlFrame.style.transform = 'translate(0,'+ -y +'px)';
	if(y < winH * 2.5) header.style.transform = 'translate(-50%,'+ -y +'px)';

	
	for (var i = 0; i < days.length; i++) {
		if(y + winH > days[i].begin && y < days[i].end) currentDay = days[i];
	}

	if(y > winH / 2 && y < fieldHeight - (winH * 5) && currentDay.data.dayNum <= 141 ) {
		date.classList.add('g-show');
	} else {
		date.classList.remove('g-show');
	}

	display_day.innerText = currentDay.data.day;
	display_count.innerText = winW < 720 ? currentDay.data.display + " deaths" : "Deaths: " + currentDay.data.display;

	if(Math.abs(scrollY - newScrollY) > 0.15 ) {
		// requestAnimationFrame(update)
		setTimeout(update, 1000/60);
	} else {
		updating = false;
	}
}

可以看到根据目前滚动条的位置设置了y值,然后根据y+窗口高度winH,设置currentDay = days[i],然后就设置display_day和display_count,显示在页面上的日期和死亡人数就会一直变化啦。

什么时候update呢?紧跟着就可以看到下面两个监听:

jquery(window).on('scroll', function(){
	newScrollY = getScrollY();
	if(!updating) update();
});

这就很明显了,当你滚动滚动条的时候就会触发update函数。

此外还有一些配套的关于滚动条的设置。
比如初始化部分

var scrollY = getScrollY(), 
	newScrollY = getScrollY(),
	updating = false;

比如调整窗口大小的时候,滚动条的比例会变嘛,就会修改一些参数

jquery(window).on('resize', lodash.debounce(function(){

	winH = window.innerHeight;
	winW = window.innerWidth;

	canvas.setAttribute('width', winW);
	canvas.setAttribute('height', winH);

	newScrollY = getScrollY();

	height = wrap.offsetHeight - (winH / 2);

	speed = fieldHeight / height;
}, 150));

还有一个要注意的地方就是,他update的数据days[i]是怎么来的呢?
其实他显式地写在了html里面内嵌的一段js代码里

	var all_deaths = [{"cumulative":1,"perDay":1,"pctByDay":0,"day":"Feb. 6","dayNum":37,"entries":[{"prettyInfo":"Patricia Dowd, 57, San Jose, Calif.","prettySnippet":"Auditor in Silicon Valley.","date":"February 6","dayNum":37,"id":"g-0"}]},
	{"cumulative":1,"perDay":1,"pctByDay":0,"day":"Feb. 26","dayNum":57,"entries":[{"prettyInfo":"Marion Krueger, 85, Kirkland, Wash.","prettySnippet":"Great-grandmother with an easy laugh.","date":"February 26","dayNum":57,"id":"g-1"}]},
	{"cumulative":1,"display":"3","perDay":1,"day":"March 1","dayNum":60,"entries":[]},
	{"cumulative":1,"display":"6","perDay":0,"day":"March 2","dayNum":61,"entries":[]},
	{"cumulative":3,"display":"10","perDay":2,"day":"March 3","dayNum":62,"entries":[]},
	……………………省略若干行
{"cumulative":96011,"display":"96,011","perDay":null,"day":"May 24","dayNum":143,"entries":[]}];

在JS里面,init()函数里就将这些数据初始化赋给了days[]

	for(var i = 0; i < all_deaths.length; i++) {

		days[i] = {
			begin: currentY,
			data: all_deaths[i]
		};

		var entries = all_deaths[i].entries;
		var spread = entries.length ? Math.floor( all_deaths[i].perDay / entries.length ) : 0;
		
		…………省略初始化的其它模块
	}

好啦,暂且就分析到这里。
初看到的时候我以为他做了很多button类的小按钮,是小人形状的,hover在上面的时候会显示对应小人的生平,按下长显示,再按下不显示……这样应该也会很酷。

你可能感兴趣的:(看看别人的,javascript,html,css)