likes
comments
collection
share

如何用css 展开清明上河图

作者站长头像
站长
· 阅读数 12

前言

上周末杭州微地震的时候,人在图书馆,听大家说"地震了,头又点晕"的时候,我丝毫没意识到,还以为是中午没睡觉的困意🥱🥱,然而我看到旁边挂着一幅画动了。这时候我就想,如果这画平时是轻卷着的,地震的时候自动展开,上面写着几个大字“地震了,大家快跑”,那不就可以挽救很多生命了么。 问题的关键是这画怎么自动展开?作为一个前端coder,我想到了css。

一、先睹为快

选一张清明上河图(局部)

如何用css 展开清明上河图

二、思路分析

就和把大象装进冰箱一样简单,左右各有两个一模一样的卷轴,中间来放画,注意几点细节:

  • 卷轴合上的时候,中间是有画布连着的
  • 卷轴展开的时候画是逐渐出来的,不是一次出来的,超出部分肯定要overflow: hidden
  • 右轴的移动和画布展开所用时间是一致的

三、代码实现

3.1 先看骨架

<body>
	<div class="container">
		<div class="leftReelWrapper">
			<div class="leftTopHandleBorder"></div>
			<div class="leftTopHandle"></div>
			<div class="leftTopReel"></div>
			<div class="leftBottomHandle"></div>
			<div class="leftBottomHandleBorder"></div>
		</div>

		<div class="content">
			<img class="pic" src='./qingming_content.png' width="469px" height="261px" />
		</div>

		<div class="rightReelWrapper">
			<div class="rightTopHandleBorder"></div>
			<div class="rightTopHandle"></div>
			<div class="rightReel"></div>
			<div class="rightBottomHandle"></div>
			<div class="rightBottomHandleBorder"></div>
		</div>
	</div>
</body>

3.2 画轴

我们以左轴为例,为避免视觉影响,先把骨架中的content 部分注释掉

如何用css 展开清明上河图 然后添加如下css代码

<style type="text/css">
body {
		background: #888;
	}

	.container {
		margin: 0 auto;
		width: 800px;
		height: 500px;
	 	background: #fff;
	 	position: relative;
	 	margin-top: 100px;
	}

	.leftReelWrapper {
		position: absolute;
		left: 50px;
		top: 50%;
		margin-top: -180px;
	}

	.leftTopReel{
		width: 20px;
		height: 300px;
		margin-left: 3px;
		background: linear-gradient(90deg, #884433, #FBBC62, #CC5F3D);
	}

	.leftTopHandle, .leftBottomHandle{
		width: 20px;
		height: 24px;
		margin-left: 3px;
		background: linear-gradient(90deg, #411C1D, #832C29, #411C1D);
	}
      /*轴上柄的末端小边*/
	.leftTopHandleBorder, .leftBottomHandleBorder {
		width: 26px;
		height: 6px;
		border-radius: 6px;
		background: linear-gradient(90deg, #411C1D, #832C29, #411C1D);
	}
</style>

现在效果是这样的(有点像金箍棒):

如何用css 展开清明上河图

一根画好之后,另外一根是一模一样的实现,只要调整下定位就可以,两根代码如下:

<style type="text/css">
	body {
		background: #888;
	}

	.container {
		margin: 0 auto;
		width: 800px;
		height: 500px;
	 	background: #fff;
	 	position: relative;
	 	margin-top: 100px;
	}

	.leftReelWrapper {
		position: absolute;
		left: 50px;
		top: 50%;
		margin-top: -180px;
	}

	/*右轴定位*/
	.rightReelWrapper {
		position: absolute;
		left: 76px;
		top: 50%;
		margin-top: -180px;
	}

	/*添加类名 .rightReel*/
	.leftTopReel, .rightReel {
		width: 20px;
		height: 300px;
		margin-left: 3px;
		background: linear-gradient(90deg, #884433, #FBBC62, #CC5F3D);
	}
	
	/*添加类名 .rightTopHandle .rightBottomHandle*/
	.leftTopHandle, .leftBottomHandle, .rightTopHandle, .rightBottomHandle {
		width: 20px;
		height: 24px;
		margin-left: 3px;
		background: linear-gradient(90deg, #411C1D, #832C29, #411C1D);
	}

	/*轴上柄的末端小边*/
	/*添加类名 .rightTopHandleBorder, .rightBottomHandleBorder*/
	.leftTopHandleBorder, .leftBottomHandleBorder, .rightTopHandleBorder, .rightBottomHandleBorder {
		width: 26px;
		height: 6px;
		border-radius: 6px;
		background: linear-gradient(90deg, #411C1D, #832C29, #411C1D);
	}
</style>

两根轴画好之后是这样子:

如何用css 展开清明上河图

3.3 展开

展开分两部分,一个是右轴的水平移动,一个是画布内容展开。

  • 先看右轴的移动
@keyframes moveReel {
	to {
		transform: translateX(500px);
	}	
}

/*右轴定位*/
.rightReelWrapper {
        ...
        // 加上这行
        animation: moveReel 5s linear 3s forwards;
}
  • 画布展开 先把骨架结构里的content放上去,不放图片

如何用css 展开清明上河图 添加如下css代码:

@keyframes expandPainting {
	to {
		width: 468px;
	    border: 20px solid #E05717;
	}
}

.content {
    position: absolute;
    /*这里使用border作为内容画布的边框,两轴静止的时候填充到中间细缝,没有设 background, 也方便直接在content里放图片,达到一种透视效果*/
    border-left: 20px solid #E05717;
    border-top: 20px solid #E05717;
    border-bottom: 20px solid #E05717;
    width: 6px;
    height: 261px;
    left: 72px;
    top: 56%;
    margin-top: -180px;
    /*这里添加动画*/
    animation: expandPainting 5s linear 3s forwards;
}

此时效果是这样的:

如何用css 展开清明上河图

3.4 放图收工

最后一步就是把图片放上去,记得加overflow:hidden

如何用css 展开清明上河图

.content {
    ...,
    overflow: hidden;
}

最终效果图如下: 如何用css 展开清明上河图

结语

这种方式自动展开画的方式对于地震预测是不可接受的🤔。 奉上完整代码