一、永远点不到的方块

示例:https://antmoe.gitee.io/project/2020/04/25/1.html
实现思路:
获取当前浏览器窗口的宽度和高度
既然是随机显示,那么位置不能超出当前浏览器的窗口。
获取div的宽度
计算宽度高度的最大值
也就说小方块移动的位置的边界。
为元素注册click(mouseover)事件
也就是鼠标点击(悬停)时触发的事件
click:点击事件
mouseover:悬停事件
源代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
overflow: hidden;
}
.box {
width: 100px;
height: 100px;
background-color: lightsalmon;
text-align: center;
line-height: 100px;
color: #333;
font-size: 14px;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
cursor: pointer;
}
</style>
</head>
<body>
<div class="box">来点我呀。。</div>
<script>
var box = document.getElementsByClassName('box')[0]
const WIDTH = window.innerWidth
const HEIGHT = window.innerHeight
const divStyle = window.getComputedStyle(box)
const divWidth = parseFloat(divStyle.width)
const divHeight = parseFloat(divStyle.height)
const maxWidth = WIDTH - divWidth
const maxHeight = HEIGHT - divHeight
box.addEventListener('mouseover', function (event) {
var left = Math.random() * maxWidth
var top = Math.random() * maxHeight
box.style.left = left + 'px'
box.style.top = top + 'px'
})
</script>
</body>
</html>
二、双击图片放大

这个有两种方式实现,
- 常规的使用两个div,大图默认是不显示的,当小图被双击后,大图就显示。
- 使用css的变形,
scale。
常规方式
https://antmoe.gitee.io/project/2020/04/25/2.html
常规方式很简单,首先是两个一模一样的div结构
<div class="default">
<img src="https://ae01.alicdn.com/kf/H68f882508c57456486095a78dca17ba9X.jpg">
</div>
<div class="scalable">
<img src="https://ae01.alicdn.com/kf/H68f882508c57456486095a78dca17ba9X.jpg">
</div>
接下来js代码就比较简单了,大体思路为:
获取default与scalable的div。
获取需要放大显示的img,也就是scalable下的img标签
为default对象设置双击事件
小图双击,则大图显示
为scalable对象设置双击事件
大图双击,则大图消失
源代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.default,
.scalable,
.scalable img {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.default {
cursor: pointer;
}
.default img {
display: block;
width: 300px;
border-radius: 20px;
box-shadow: 0 0 25px 5px #d9d9d9;
}
.scalable {
transform: all 3s;
}
.scalable img {
display: block;
height: 700px;
border-radius: 40px;
width: 0;
height: 0;
transition: all 1s;
}
</style>
</head>
<body>
<div class="default">
<img src="https://ae01.alicdn.com/kf/H68f882508c57456486095a78dca17ba9X.jpg">
</div>
<div class="scalable">
<img src="https://ae01.alicdn.com/kf/H68f882508c57456486095a78dca17ba9X.jpg">
</div>
<script>
var defaultElement = document.getElementsByClassName('default')[0]
var scalableElement = document.getElementsByClassName('scalable')[0]
var scalableImg = scalableElement.firstElementChild
defaultElement.addEventListener('dblclick', function () {
scalableImg.style.width = '900px'
scalableImg.style.height = '600px'
})
scalableElement.addEventListener('dblclick', function () {
scalableImg.style.width = '0px'
scalableImg.style.height = '0px'
})
</script>
</body>
</html>
scale方式
https://antmoe.gitee.io/project/2020/04/25/3.html
与常规方式较为相似,但只需要一个div即可。
当双击时,为img设置变形属性scale即可。
至于判断第一次还是第二次,可以用一个数字变量,用于记录。
源代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.default,
.scalable,
.scalable img {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.default {
cursor: pointer;
}
.default img {
display: block;
width: 300px;
border-radius: 20px;
box-shadow: 0 0 25px 5px #d9d9d9;
transition: all 1s;
}
</style>
</head>
<body>
<div class="default">
<img src="https://ae01.alicdn.com/kf/H68f882508c57456486095a78dca17ba9X.jpg">
</div>
<script>
var defaultElement = document.getElementsByClassName('default')[0]
var imgElement = defaultElement.firstElementChild
var num = 0;
defaultElement.addEventListener('dblclick', function () {
num++
if (num % 2 === 1) {
imgElement.style.transform = 'scale(3)'
} else {
imgElement.style.transform = 'scale(1)'
}
})
</script>
</body>
</html>
三、鼠标经典事件
https://antmoe.gitee.io/project/2020/04/25/4.html
为了测试鼠标事件,需要一个div。
<div class="box">来点我呀。。</div>
很简单的一个div即可。
然后简单的获取到他,方便后续测试
var body = document.body
var box = document.getElementsByClassName('box')[0]
鼠标悬停
box.addEventListener('mouseover', function () {
box.textContent = '在我上面了。'
})

鼠标离开
box.addEventListener('mousedown', function () {
box.textContent = '选中我了。。'
flag = true
})
上述图中可以看到,鼠标移动到div上,即变化了文字。鼠标离开后文字又变了回来。
鼠标跟随事件(不包含释放)
这里需要在引入一个变量用于标志是否触发跟随事件。并且在按下事件中将开关打开。
var flag = false;
body.addEventListener('mousemove', function (event) {
if (flag) {
box.style.left = event.pageX + 'px'
box.style.top = event.pageY + 'px'
}
})

鼠标按下事件(没有释放)
box.addEventListener('mousedown', function () {
box.textContent = '选中我了。。'
flag = true
})
如上图,当鼠标点击后。开启跟随事件的开关。
鼠标按键抬起
box.addEventListener('mouseup', function () {
box.style.left = event.pageX + 'px'
box.style.top = event.pageY + 'px'
flag = false
})

当鼠标放开后,div就固定到了鼠标的位置。
四、自定义鼠标右键
https://antmoe.gitee.io/project/2020/04/25/5.html

自定义鼠标右键:在html结构方面可以使用一个无序列表实现。
<ul id="menu">
<li>剪切</li>
<li>复制</li>
<li>粘贴</li>
<li>段落格式</li>
<li>批注</li>
<li>插入链接</li>
</ul>
在js方面,要做的其实有两点:
阻止阻止或禁止浏览器窗口提供的默认右键菜单
body.addEventListener('contextmenu', function (event) {
event.preventDefault()
})
需要注意的是:当页面内无内容时,body是无高度的,因此需要为body设置高度。否则为body绑定事件无法被触发。
var body = document.body
body.style.height = window.innerHeight + 'px'
当右键被点击时显示自己的div,左键时隐藏
判断点击的是鼠标什么按键,所使用的是event事件的button属性。
鼠标左键
event.button === 0
鼠标中键
event.button === 1
鼠标右键
event.button === 2
源代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
box-sizing: border-box;
}
#menu {
list-style: none;
margin: 0;
padding: 10px;
width: 100px;
height: 202px;
border: 1px solid #d9d9d9;
border-radius: 2px;
position: absolute;
display: none;
}
#menu li {
height: 30px;
size: 12px;
color: rgba(0, 0, 0, .5);
line-height: 30px;
}
#menu li:nth-of-type(5) {
border-top: 1px solid #d9d9d9;
border-bottom: 1px solid #d9d9d9;
}
</style>
</head>
<body>
<ul id="menu">
<li>剪切</li>
<li>复制</li>
<li>粘贴</li>
<li>段落格式</li>
<li>批注</li>
<li>插入链接</li>
</ul>
<script>
var body = document.body
body.style.height = window.innerHeight + 'px'
var menu = document.getElementById('menu')
body.addEventListener('contextmenu', function (event) {
event.preventDefault()
})
body.addEventListener('mousedown', function (event) {
if (event.button === 2) {
menu.style.left = event.clientX + 'px'
menu.style.top = event.clientY + 'px'
menu.style.display = 'block'
} else if (event.button === 0) {
menu.style.display = 'none'
}
})
</script>
</body>
</html>
五、 滑动一定量时,固定导航
https://antmoe.gitee.io/project/2020/04/26/1.html

如图,模拟页面中的一个小导航,当页面滚动到一定程度时,将其固定。
关于滚动事件
滚动事件可以有两个scroll与wheel
判断当前滚动的高度
源代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
box-sizing: border-box;
}
body {
height: 2000px;
}
.menu {
width: 800px;
list-style: none;
padding: 0;
margin: 0;
overflow: hidden;
background-color: #d9d9d9;
position: relative;
top: 300px;
}
.menu li {
width: 100px;
height: 50px;
float: left;
text-align: center;
line-height: 50px;
}
.menu li a {
height: 22px;
display: block;
text-decoration: none;
color: #333;
line-height: 22px;
margin: 14px 0;
border-right: .5px solid #9b9b9b;
}
.menu li:last-of-type a {
border: none;
}
</style>
</head>
<body>
<ul class="menu">
<li><a href="#">最新文章</a></li>
<li><a href="#">大公司</a></li>
<li><a href="#">消费</a></li>
<li><a href="#">娱乐</a></li>
<li><a href="#">前沿技术</a></li>
<li><a href="#">汽车交通</a></li>
<li><a href="#">区块链</a></li>
<li><a href="#">技能Get</a></li>
</ul>
<script>
var html = document.documentElement
var menu = document.getElementsByClassName('menu')[0]
var menutop = parseFloat(window.getComputedStyle(menu).top)
document.addEventListener('wheel', function () {
var scrollTop = html.scrollTop
if (scrollTop >= menutop) {
menu.style.position = 'fixed'
menu.style.top = 0
} else {
menu.style.position = 'relative'
menu.style.top = '300px'
}
})
</script>
</body>
</html>
六、 轮播图
https://antmoe.gitee.io/project/2020/04/26/index.html

静态样式与小米轮播图大体相同。但是左右的按钮只需要各一个即可。
由于图片是出现消失式,所以只需要用透明度+层级控制图片的出现即可。因此js大致逻辑为:当点击右按钮或者左按钮时切换下一张图片。
可以用一个整数变量控制第几个元素。
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小米首页轮播图</title>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
.container {
width: 1226px;
height: 460px;
background-color: lightcyan;
margin: 100px auto;
position: relative;
}
.container .imgList {
width: 100%;
position: absolute;
}
.container .imgList img {
display: block;
width: 100%;
height: auto;
position: absolute;
left: 0;
top: 0;
opacity: 0;
z-index: 0;
transition: all 1s;
}
.container .slide-controls {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
.container .slide-controls .slide-left,
.container .slide-controls .slide-right {
width: 41px;
height: 69px;
position: absolute;
top: 50%;
transform: translateY(-50%);
background-image: url(https://i1.mifile.cn/f/i/2014/cn/icon/icon-slides.png);
cursor: pointer;
z-index: 2;
}
.container .slide-controls .slide-left {
left: 0;
background-position: -84px 0;
}
.container .slide-controls .slide-left:hover {
background-position: 0 0;
}
.container .slide-controls .slide-right {
right: 0;
background-position: -124px 0;
}
.container .slide-controls .slide-right:hover {
background-position: -42px 0;
}
.container .nav {
width: 100px;
height: 20px;
position: absolute;
left: 50%;
right: 0;
bottom: 8px;
transform: translateX(-50%);
z-index: 2;
}
.container .nav .slide-nav {
width: 12px;
height: 12px;
border: 2px solid #fff;
border-color: hsla(0, 0%, 100%, .3);
border-radius: 10px;
background: rgba(0, 0, 0, .4);
cursor: pointer;
margin: 0 4px;
float: left;
z-index: 3;
}
.container .nav .slide-nav:hover {
background: hsla(0, 0%, 100%, .4);
border-color: rgba(0, 0, 0, .4);
}
</style>
</head>
<body>
<div class="container">
<div class="imgList">
<img src="https://ae01.alicdn.com/kf/U1a6b653720d845c682f97d2fcf75c22f6.png" />
<img src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/755aca9487082e7698e16f17cfb70839.jpg" />
<img src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/e5b37cdb85b3b93b5938cc508a10c906.jpg" />
<img src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/e909ef0e50960f61a730380013bc960a.jpg" />
<img src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/6bd4174b8c5aad67a64864a5716ad152.jpg" />
</div>
<div class="slide-controls">
<div class="slide-left"></div>
<div class="slide-right"></div>
</div>
<div class="nav">
<div class="slide-nav"></div>
<div class="slide-nav"></div>
<div class="slide-nav"></div>
<div class="slide-nav"></div>
<div class="slide-nav"></div>
</div>
</div>
<script>
var imgList = document.getElementsByClassName('imgList')[0]
var imageElements = imgList.getElementsByTagName('img')
var navElement = document.getElementsByClassName('nav')[0]
var slideElements = navElement.getElementsByClassName('slide-nav')
var num = 0
var slideControl = document.getElementsByClassName('slide-controls')[0]
var slideLeft = slideControl.getElementsByClassName('slide-left')[0]
var slideRight = slideControl.getElementsByClassName('slide-right')[0]
var arr = []
for (var i = 0; i < slideElements.length; i++) {
arr.push(slideElements[i])
}
function show(num) {
imageElements[num].style.opacity = 1
imageElements[num].style.zIndex = 1
slideElements[num].style.backgroundColor = 'hsla(0, 0%, 100%, .4)'
slideElements[num].style.borderColor = 'rgba(0, 0, 0, .4)'
}
function hidden() {
for (var i = 0; i < slideElements.length; i++) {
imageElements[i].style.opacity = 0
imageElements[i].style.zIndex = 0
slideElements[i].style.backgroundColor = null
slideElements[i].style.borderColor = null
}
}
show(0)
slideRight.addEventListener('click', function () {
num++
console.log(num)
hidden()
if (num === imageElements.length) {
num = 0
show(num)
} else {
show(num)
}
})
slideLeft.addEventListener('click', function () {
console.log(num)
hidden()
if (num <= 0) {
num = imageElements.length - 1
show(num)
} else {
show(num - 1)
num--
}
})
navElement.addEventListener('click', function (event) {
var target = event.target
num = arr.indexOf(target)
if (target.className === 'slide-nav') {
hidden()
show(num)
}
})
</script>
</body>
</html>
七、 轮播图升级版
https://antmoe.gitee.io/project/2020/04/27/index.html
大致思路如下:
- 进入文章后,需要获取所有的图片。并将所有的图片插入到轮播图的图片容器中。
- 双击(单击)文章文章的某个图片,将轮播图容器显示来。
- 点击右侧或左侧按钮,使图片进行正常的切换。
与上一个轮播图不同的是,显示轮播的容器需要根据用户点击的图片进行动态添加,并且每次退出后应该清除,防止下次进入出现问题。
在判断用户点击的图片时可以用到一个小技巧,先将全部图片插入到一个列表,将点击的对象判断在列表内的索引即可。
var imageArr = [];
var imageElement = imageElements[i];
imageArr.push(imageElement);
slideNum = imageArr.indexOf(targetElement);
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>双击放大轮播图</title>
<style>
* {
box-sizing: border-box;
}
.article-wapper {
width: 694px;
overflow: hidden;
font-family: PingFang SC, Lantinghei SC, Helvetica Neue, Helvetica,
Arial, Microsoft YaHei, 微软雅黑, STHeitiSC-Light, simsun, 宋体,
WenQuanYi Zen Hei, WenQuanYi Micro Hei, "sans-serif";
word-break: break-word;
margin: 50px auto;
}
.article-wapper h1 {
font-size: 30px;
color: #262626;
letter-spacing: 0;
text-align: justify;
line-height: 42px;
font-weight: 400;
margin-bottom: 20px;
}
.article-wapper .content {
font-size: 16px;
color: #262626;
letter-spacing: 0;
text-align: justify;
line-height: 30px;
}
.article-wapper .content p {
margin-bottom: 26px;
word-wrap: break-word;
}
.article-wapper .content p a {
text-decoration: none;
color: #262626;
border: solid #999;
border-width: 0 0 1px;
padding: 0 0 1px;
word-wrap: break-word;
}
.article-wapper .content p img {
max-width: 690px;
display: block;
border-radius: 5px;
margin: 30px auto;
cursor: pointer;
}
.article-wapper .content h2 {
font-weight: 600;
margin: 30px 0 14px;
font-size: 20px;
line-height: 28px;
position: relative;
color: #4285f4;
}
.image-slide {
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.8);
display: none;
}
.image-slide .image-list,
.image-slide .slide-controls {
width: 80%;
height: 80%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.image-slide .image-list img {
width: 850px;
display: block;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
opacity: 0;
z-index: 0;
transition: all 1s;
}
.image-slide .slide-controls .slide-left,
.image-slide .slide-controls .slide-right {
width: 41px;
height: 69px;
position: absolute;
top: 50%;
transform: translateY(-50%);
background-image: url(https://i1.mifile.cn/f/i/2014/cn/icon/icon-slides.png);
cursor: pointer;
z-index: 2;
}
.image-slide .slide-controls .slide-left {
left: 0;
background-position: -84px 0;
}
.image-slide .slide-controls .slide-left:hover {
background-position: 0 0;
}
.image-slide .slide-controls .slide-right {
right: 0;
background-position: -124px 0;
}
.image-slide .slide-controls .slide-right:hover {
background-position: -42px 0;
}
</style>
</head>
<body>
<div class="article-wapper">
<h1>究竟是谁制造了“瑞幸”之殇?</h1>
<div class="content">
<p>
编者按:本文来自微信公众号<a
href="https://mp.weixin.qq.com/s/yoRSqdXpk4JA-2_Zg0ojig">“品牌几何”(ID:brand-vista)</a>,作者:李刚健,36氪经授权发布。
</p>
<p>几何君有话说:</p>
<p>
这段时间,瑞幸掀起了不小的风波。当它站在风口浪尖之时,周围不断发出了各种不同的声音。今天几何君分享一篇李刚健老师的文章,究竟是谁制造了瑞幸之殇呢?
</p>
<h2 label="一级标题">
01. <span style="letter-spacing: 0px;">美国最具创新精神公司</span>
</h2>
<p>
曾有一家世界上最大的能源公司,连续六年被《财富》杂志评选为“美国最具创新精神公司”,2000年披露的营业额达1010亿美元之巨,拥有约21000名雇员,这家公司叫安然。
</p>
<p>
2001年年初,一家有着良好声誉的投资机构老板吉姆·切欧斯公开对安然的盈利模式表示了怀疑。他指出,虽然安然的业务看起来很辉煌,但实际上赚不到什么钱,也没有人能够说清安然是怎么赚钱的。10月22日,美国证券交易委员会要求公司自动提交某些交易的细节内容。并最终于10月31日开始对安然及其合伙公司进行正式调查。11月8日,安然被迫承认做了假账,虚报数字让人瞠目结舌:自1997年以来,安然虚报盈利共计近6亿美元。11月30日,安然股价跌至0.26美元,市值由峰值时的800亿美元跌至2亿美元。
</p>
<p>
12月2日,安然正式向破产法院申请破产保护,破产清单中所列资产高达498亿美元,成为美国历史上最大的破产企业。
</p>
<p>
<img src="https://img.36krcdn.com/20200427/v2_be0d7fc527eb41b5ac7f88a35ae6d9a0_img_000"
data-img-size-val="1080,730" />
</p>
<h2 label="一级标题">
02. <span style="letter-spacing: 0px;">元气满满的瑞幸?</span>
</h2>
<p>
将近20年以后,有一家中国的咖啡连锁新贵,亏着钱做着生意,也在美国上了市,号称是中国咖啡业的领军品牌,这个公司叫瑞幸。
</p>
<p>
也是年初,卡森·布洛克组织了92名全职和1418名兼职调查员,在全国45个城市2213家瑞幸门店,收集了25000多张小票,进行了10000个小时的门店录像,发布了瑞幸的做空报告。随后,瑞幸发布公告坚决否认报告中的所有指控,认为该报告的论证方式存在缺陷,报告中包含的所谓证据无确凿事实依据,且报告中的指控均基于毫无根据的推测和对事件的恶意解释。
</p>
<p>
直到愚人节后的第一天,安永不敢在年报上签字,瑞幸才不得不自曝,并且迅速找了一个背锅侠。尽管随之股价大跌,瑞幸自己却觉得“元气满满”。
</p>
<p>
之后的口诛笔伐尽管铺天盖地,然而4月3日瑞幸的店门口居然排起了长队,据说是怕优惠券来不及用完的群众。之后经过几周的冷清,4月14号,有记者宣称上海门店挺过寒冬,订单恢复正常。
</p>
<p>
<img src="https://img.36krcdn.com/20200427/v2_1d93ac5c10184d178dcb0b3305c11386_img_000"
data-img-size-val="1080,734" />
</p>
<h2 label="一级标题">
03. <span style="letter-spacing: 0px;">瑞幸算是一个品牌吗?</span>
</h2>
<p>
看上去,尽管从出生之始就一直有人唱衰瑞幸,可是凭着对媒介公关的高明操控,瑞幸每次都能度过难关。也许老陆早就明白一个道理:你们能花多少成本和时间再找那么多人来收集新的证据呢?做空者该赚的也赚完了,我依然还可以讲故事,可以利用消费者的劣根性做游戏。
</p>
<p>
有人问瑞幸算是一个品牌吗?有人说不是,它只是一门生意;也有人说它连生意都不是,只是资本游戏的一个载体。我比较倾向于最后一种理解。说老陆在做游戏,就像是营造了一个他的《西部世界》:真正的目的不是产品本身,而是消费者数据。随着技术的发展,消费者数据就是消费者心智——我可以比你更了解你,"你是真的吗?""如果你分辨不出来,那还重要吗?"。
</p>
<p>
福特用机器人收集数据,老陆用咖啡收集数据(实际上也可以用别的,只不过恰好用咖啡编了点故事,尽管蹩脚,但是中国有智商税,大家都懂的)。老陆把咖啡卖给了普通消费者,把数据作为价值核心通过各种金融手段(公开上市,质押等等)卖给了普通投资者,完美的闭环。本来,两者就是同一群人,而老陆的NB之处在于通过地域使他们没有重合:亏了国外投资者(幸好大部分国内投资者不买美股),让国内消费者赚了便宜。因为老陆知道,这样的分割舆论上更好操控。
</p>
<p>
然而,我们在快意的指责瑞幸的管理团队和那帮无良的保荐承销机构(他们都是精英中的精英)的同时,有没有想过作为一个普通消费者,我们每个人自己的责任吗?
</p>
<p>
<img src="https://img.36krcdn.com/20200427/v2_3851c681585849499fc0e3e4268c61b9_img_000"
data-img-size-val="1080,766" />
</p>
<p>
很多很多年以前,那时我还很年轻,还没有家庭和孩子,任职于一家国际著名的品牌咨询公司。适逢公司旅游,两岸三地的同事共赴普吉岛,享受阳光和沙滩。一位业界德高望重的前辈曾经质问过我:你们穿着那些昂贵的品牌服装,真的觉得适合你们自己本人的气质和价值观吗?因为很多人看起来穿着特别不协调,不是身材尺寸的原因。
</p>
<p>
答案大家也都很清楚:因为那些品牌的价格能体现身份。是的,那时的我们以为价格=身份感,我们却不知道价格背后的品牌态度和价值观才是更深层次的原因,我们搞错了因果关系。也正是我所在的这家公司,因为对转基因产业的反对态度,拒绝了当时和孟山都合作的机会。
</p>
<p>
当下整个中国的消费群体都被“成功学”和“占便宜”的商业逻辑左右,都觉得只有成功才是判断真理的唯一标准,而性价比永远是吸引流量的利器。几乎所有品类的东西都越来越便宜,真正赚钱的只有平台和中介(基本处于垄断的状态),使得几乎所有的生产者(最终也是消费者)都面临苦难的境地(这对中国经济的长期负面因素并不是我能关心和解决的)。
</p>
<p>
<img src="https://img.36krcdn.com/20200427/v2_fc67a520b6a64627ba466a1f4465a876_img_000"
data-img-size-val="777,423" />
</p>
<p>
归根到底,因为我们是这样的消费逻辑:只要商家给我好处,个人数据并不值钱,反正我也不是什么大人物,数据被人拿去最多被骚扰一下,又能怎样呢?我们绝不会因为不喜欢一个品牌,有便宜也不去占,有羊毛不薅是傻子。因此,不断有瑞幸这样的商业模式出现:给你便宜,拿你数据,然后用你的数据编故事(用户运营)说给各级市场的投资者,各怀利益,总有人接棒,最终套现走人,实现一个资本游戏闭环。
</p>
<p>
在这样的情况下,品牌也就完全不需要营造什么价值观(那些泛泛的讲创造美好生活之类的都是空谈,并没有价值观),消费者也不需要认同。这事儿就像皇帝的新衣,人人知道答案,但还是不断发生。至于造假,那都是战术。瑞幸算是倒霉,线下能找到证据,很多线上流量编故事的数据根本无法考证。
</p>
<p>
等到哪一天我徜徉在线上线下的世界里,面对所有的打折一无所动,不再关心什么6.18和双11,只在需要的时候买价值观被自己认同的品牌(当然首先它的产品是可靠的),还会有瑞幸这样的商业模式出现吗?
</p>
<p>
因为品牌有不同的价值观,所以会有不同的溢价。我们愿意因为价值观多付合理的费用吗?
</p>
<p>*图片来源:网络</p>
</div>
</div>
<div class="image-slide">
<div class="image-list"></div>
<div class="slide-controls">
<div class="slide-left"></div>
<div class="slide-right"></div>
</div>
</div>
<script>
var contentElement = document.getElementsByClassName("content")[0];
var imageElements = contentElement.getElementsByTagName("img");
var imageArr = [];
var slideElement = document.getElementsByClassName("image-slide")[0];
var listElement = slideElement.getElementsByClassName("image-list")[0];
var slideImageElements = listElement.getElementsByTagName("img");
for (var i = 0; i < imageElements.length; i++) {
var imageElement = imageElements[i];
var imageLink = imageElement.getAttribute("src");
var newImageElement = document.createElement("img");
newImageElement.setAttribute("src", imageLink);
listElement.appendChild(newImageElement);
imageArr.push(imageElement);
}
var slideNum = 0,
prev = 0;
var length = slideImageElements.length - 1;
var bodyElement = document.body;
contentElement.addEventListener("dblclick", function (event) {
var targetElement = event.target;
if (targetElement.nodeName === "IMG") {
slideElement.style.display = "block";
slideNum = imageArr.indexOf(targetElement);
slideImageElements[slideNum].style.opacity = 1;
slideImageElements[slideNum].style.zIndex = 1;
bodyElement.style.overflow = "hidden";
}
});
slideElement.addEventListener("dblclick", function () {
slideElement.style.display = "none";
bodyElement.style.overflow = "auto";
slideImageElements[slideNum].style.opacity = 0;
slideImageElements[slideNum].style.zIndex = 0;
});
var slideControl = slideElement.getElementsByClassName(
"slide-controls"
)[0];
var slideLeft = slideControl.getElementsByClassName("slide-left")[0];
var slideRight = slideControl.getElementsByClassName("slide-right")[0];
slideRight.addEventListener("click", function () {
if (slideNum < length) {
slideNum++;
prev = slideNum - 1;
} else if (slideNum === length) {
slideNum = 0;
prev = length;
}
slideImageElements[slideNum].style.opacity = 1;
slideImageElements[slideNum].style.zIndex = 1;
slideImageElements[prev].style.opacity = 0;
slideImageElements[prev].style.zIndex = 0;
});
slideLeft.addEventListener("click", function () {
if (slideNum > 0) {
slideNum--;
prev = slideNum + 1;
} else if (slideNum === 0) {
slideNum = length;
prev = 0;
}
slideImageElements[slideNum].style.opacity = 1;
slideImageElements[slideNum].style.zIndex = 1;
slideImageElements[prev].style.opacity = 0;
slideImageElements[prev].style.zIndex = 0;
});
</script>
</body>
</html>
九、横向轮播图
https://antmoe.gitee.io/project/2020/05/17/1_轮播图切换动画.html
实现静态效果不难,只需要控制其left效果即可。
如果加入动画效果,只能利用定时器.
左右按钮的切换大致相同,只以右按钮为例:
- 记录当前图片的索引(全局变量保存)
- 判断尺寸
- 利用定时器完成累加/减
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小米首页轮播图</title>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
.container {
width: 1226px;
height: 460px;
background-color: lightcyan;
overflow: hidden;
margin: 100px auto;
position: relative;
}
.container .imgList {
width: 6130px;
position: absolute;
}
.container .imgList img {
display: block;
width: 1226px;
height: auto;
float: left;
}
.container .slide-controls {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
.container .slide-controls .slide-left,
.container .slide-controls .slide-right {
width: 41px;
height: 69px;
position: absolute;
top: 50%;
transform: translateY(-50%);
background-image: url(https://i1.mifile.cn/f/i/2014/cn/icon/icon-slides.png);
cursor: pointer;
z-index: 2;
}
.container .slide-controls .slide-left {
left: 0;
background-position: -84px 0;
}
.container .slide-controls .slide-left:hover {
background-position: 0 0;
}
.container .slide-controls .slide-right {
right: 0;
background-position: -124px 0;
}
.container .slide-controls .slide-right:hover {
background-position: -42px 0;
}
.container .nav {
width: 100px;
height: 20px;
position: absolute;
left: 50%;
right: 0;
bottom: 8px;
transform: translateX(-50%);
z-index: 2;
}
.container .nav .slide-nav {
width: 12px;
height: 12px;
border: 2px solid #fff;
border-color: hsla(0, 0%, 100%, .3);
border-radius: 10px;
background: rgba(0, 0, 0, .4);
cursor: pointer;
margin: 0 4px;
float: left;
z-index: 3;
}
.container .nav .slide-nav:hover {
background: hsla(0, 0%, 100%, .4);
border-color: rgba(0, 0, 0, .4);
}
</style>
<script type="text/javascript" nonce="e9b48b8ca3e64a6a85e757b4795"
src="//local.adguard.org?ts=1589675716165&type=content-script&dmn=antmoe.gitee.io&css=1&js=1&gcss=1&rel=1&rji=1&stealth=1&uag="></script>
<script type="text/javascript" nonce="e9b48b8ca3e64a6a85e757b4795"
src="//local.adguard.org?ts=1589675716165&name=AdGuard%20Popup%20Blocker&name=AdGuard%20Assistant&name=AdGuard%20Extra&type=user-script"></script>
</head>
<body>
<div class="container">
<div class="imgList">
<img src="https://ae01.alicdn.com/kf/U1a6b653720d845c682f97d2fcf75c22f6.png" />
<img src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/755aca9487082e7698e16f17cfb70839.jpg" />
<img src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/e5b37cdb85b3b93b5938cc508a10c906.jpg" />
<img src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/e909ef0e50960f61a730380013bc960a.jpg" />
<img src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/6bd4174b8c5aad67a64864a5716ad152.jpg" />
</div>
<div class="slide-controls">
<div class="slide-left"></div>
<div class="slide-right"></div>
</div>
<div class="nav">
<div class="slide-nav"></div>
<div class="slide-nav"></div>
<div class="slide-nav"></div>
<div class="slide-nav"></div>
<div class="slide-nav"></div>
</div>
</div>
<script>
var container = document.getElementsByClassName('container')[0]
var imgList = container.getElementsByClassName('imgList')[0]
var rightBtn = document.getElementsByClassName('slide-right')[0]
var leftBtn = document.getElementsByClassName('slide-left')[0]
var nav = container.getElementsByClassName('nav')[0]
var slide_nav = container.getElementsByClassName('slide-nav')
var indexStart
var auto_num
var img_width = 1226
var img_num = imgList.childElementCount
var img_index = 0
var pre_nav_num = 0
function showNav(num) {
slide_nav[num].style.background = 'hsla(0, 0%, 100%, .4)'
slide_nav[num].style.borderColor = 'rgba(0, 0, 0, .4)'
slide_nav[pre_nav_num].style.borderColor = 'hsla(0, 0%, 100%, .4)'
slide_nav[pre_nav_num].style.background = 'rgba(0, 0, 0, .4)'
}
auto()
rightBtn.addEventListener('click', function () {
if (img_index < img_num - 1) {
pre_nav_num = img_index
indexStart = -(img_index * img_width)
img_index++
} else {
img_index = 0
indexStart = 1226
pre_nav_num = 4
}
clearInterval(auto_num)
moveLeft()
setTimeout(auto, 5000)
showNav(img_index)
})
leftBtn.addEventListener('click', function () {
if (img_index == 0) {
img_index = 4
indexStart = -6130
pre_nav_num = 0
} else {
pre_nav_num = img_index
indexStart = -(img_index * img_width)
img_index--
}
moveRight()
showNav(img_index)
})
nav.addEventListener('click', function (e) {
var nav_list = []
for (var i = 0; i < nav.childElementCount; i++) {
nav_list.push(slide_nav[i])
slide_nav[i].style.borderColor = 'hsla(0, 0%, 100%, .4)'
slide_nav[i].style.background = 'rgba(0, 0, 0, .4)'
}
var target = e.target
if (target.className === 'slide-nav') {
img_index = nav_list.indexOf(target)
slide_nav[img_index].style.borderColor = 'hsla(0, 0%, 100%, .4)'
slide_nav[img_index].style.background = 'rgba(255, 255, 255, 0.4)'
imgList.style.left = -(img_index * img_width) + 'px'
}
})
function moveLeft() {
if (indexStart <= -(img_index * img_width)) {
clearInterval(t)
} else {
indexStart -= 10
imgList.style.left = indexStart + 'px'
var t = setTimeout(moveLeft, 1)
}
}
function moveRight() {
if (indexStart >= -(img_index * img_width)) {
clearInterval(t)
} else {
indexStart += 10
imgList.style.left = indexStart + 'px'
var t = setTimeout(moveRight, 1)
}
}
function auto() {
auto_num = setInterval(function () {
if (img_index < img_num - 1) {
pre_nav_num = img_index
indexStart = -(img_index * img_width)
img_index++
} else {
img_index = 0
indexStart = 1226
pre_nav_num = 4
}
moveLeft()
showNav(img_index);
}, 5000)
}
</script>
</body>
</html>
八、键盘事件
https://antmoe.gitee.io/project/2020/04/28/index.html
在键盘事件中,可以为<html> <body> document 对象绑定。
var html = document.documentElement
var body = document.body
html.addEventListener("keydown", function (event) {
console.log(event)
})
body.addEventListener("keydown", function (event) {
console.log(event)
})
document.addEventListener("keydown", function (event) {
console.log(event)
})

但是在键盘事件提供的三个事件中只有keydown keyup,可以监控到上下左右按键。
html.addEventListener("keydown", function (event) {
console.log(event)
})
html.addEventListener('keypress', function (event) {
console.log(event)
})
html.addEventListener("keyup", function (event) {
console.log(event)
})


- code属性: 前缀 + 键盘信息
- key属性: 键盘信息
- keyCode属性: 键盘的Unicode信息
- which属性: 键盘的Unicode信息
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 100px;
height: 100px;
background-color: coral;
position: absolute;
left: 20px;
top: 30px;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var html = document.documentElement
var body = document.body
var box = document.getElementsByClassName('box')[0]
html.addEventListener("keydown", function (event) {
var style = window.getComputedStyle(box)
var boxLeft = parseFloat(style.left)
var boxTop = parseFloat(style.top)
switch (event.key) {
case 'ArrowUp':
boxTop -= 10
break
case 'ArrowDown':
boxTop += 10
break
case 'ArrowLeft':
boxLeft -= 10
break
case 'ArrowRight':
boxLeft += 10
break
}
box.style.top = boxTop + 'px'
box.style.left = boxLeft + 'px'
})
</script>
</body>
</html>
九、限制方块滑动位置
https://antmoe.gitee.io/project/2020/04/29/2.html
基于上边的移动方块案例,可以为方块加个限制范围。思路也很简单。
获取限制容器的宽度及高度
计算出移动div的可移动最大范围
const maxLeft = containerWidth - boxWidth,maxTop = containerHeight - boxHeight
每次移动时,判断是否超过了范围
如果超过
不移动
没有超过
移动
移动的距离大于到边界的距离
移动距离为到边界的距离
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
width: 600px;
height: 500px;
border: 1px solid black;
position: relative;
margin: 100px auto;
}
.box {
width: 100px;
height: 100px;
background-color: coral;
position: absolute;
left: 20px;
top: 30px;
}
</style>
</head>
<body>
<div class="container">
<div class="box"></div>
</div>
<script>
var container = document.getElementsByClassName("container")[0]
var containerStyle = window.getComputedStyle(container)
var containerWidth = parseFloat(containerStyle.width)
var containerHeight = parseFloat(containerStyle.height)
var box = document.getElementsByClassName('box')[0]
var boxStyle = window.getComputedStyle(box)
var boxWidth = parseFloat(boxStyle.width)
var boxHeight = parseFloat(boxStyle.height)
const minLeft = 0, minTop = 0,
maxLeft = containerWidth - boxWidth,
maxTop = containerHeight - boxHeight
document.addEventListener("keydown", function (event) {
var style = window.getComputedStyle(box)
var boxLeft = parseFloat(style.left)
var boxTop = parseFloat(style.top)
switch (event.key) {
case 'ArrowUp':
if ((boxTop - 10) > minTop) {
boxTop -= 10
} else if ((boxTop - 10) <= minTop && (boxTop - 10) > -10) {
boxTop -= boxTop
}
break
case 'ArrowDown':
if ((boxTop + 10) < maxTop) {
boxTop += 10
} else if ((boxTop + 10) >= maxTop && boxTop < maxTop) {
boxTop += maxTop - boxTop
}
break
case 'ArrowLeft':
if ((boxLeft - 10) > minLeft) {
boxLeft -= 10
} else if ((boxLeft - 10) <= minLeft && (boxLeft - 10) > -10) {
boxLeft -= boxLeft
}
break
case 'ArrowRight':
if ((boxLeft + 10) < maxLeft) {
boxLeft += 10
} else if ((boxLeft + 10) >= maxLeft && boxLeft < maxLeft) {
boxLeft += maxLeft - boxLeft
}
break
}
box.style.top = boxTop + 'px'
box.style.left = boxLeft + 'px'
})
</script>
</body>
</html>
十、组合键提示
https://antmoe.gitee.io/project/2020/04/29/2.html

- 定义一个数组,用于存储按下的按键。
- 当按键按下去的时候,获取按键并添加到数组。
- 当按键松开的时候,从数组中删除按键
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组合键</title>
<style>
.shortcuts {
width: 240px;
height: 80px;
background-color: rgba(0, 0, 0, .5);
border-radius: 10px;
font-size: 24px;
font-weight: 800;
text-align: center;
line-height: 80px;
color: #fff;
position: fixed;
left: 50%;
bottom: 10px;
transform: translateX(-50%);
opacity: 0;
}
</style>
</head>
<body>
<div class="shortcuts"></div>
<script>
var divElement = document.getElementsByClassName('shortcuts')[0]
var keyArr = []
var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z'
]
document.addEventListener('keydown', function (event) {
var key = event.key
key = letters.indexOf(key) !== -1 ? key.toUpperCase() : key
if (key !== keyArr[keyArr.length - 1] || keyArr.length === 0) {
keyArr.push(key)
}
switch (keyArr.length) {
case 2:
divElement.textContent = keyArr[0] + ' + ' + keyArr[1]
divElement.style.opacity = 1
break
case 3:
divElement.textContent = keyArr[0] + ' + ' + keyArr[1] + ' + ' + keyArr[2]
divElement.style.opacity = 1
break
}
})
document.addEventListener('keyup', function (event) {
var key = event.key
keyArr = []
console.log(keyArr)
divElement.textContent = ''
divElement.style.opacity = 0
})
</script>
</body>
</html>
获取焦点事件
获取焦点即鼠标按上时的事件,类似css中的focus伪类。
var username = document.getElementById('username')
username.addEventListener('focus', function () {
username.value = ''
})
username.addEventListener('blur', function () {
username.value = '请输入你的用户名'
})
加载事件
加载事件可以理解为当页面加载完成后的事件或者页面加载时的事件。
window.onload = function () {
var username = document.getElementById('username')
console.log(username.value)
}
var imgElement = document.getElementById('img')
imgElement.addEventListener('load', function () {
console.log('表示图片已加载完毕...')
})
变化大小事件
变化大小用于监听浏览器窗口的大小变化
window.addEventListener('resize', function () {
console.log(window.innerWidth, window.innerHeight)
})
change事件
顾名思义,即当发生变化时所触发的事件。
var city = document.getElementById('city')
city.addEventListener('change', function () {
console.log(city.value)
})
表单提交事件
当表单提交时所触发的事件。
var form = document.getElementById('login')
form.addEventListener('submit', function (event) {
console.log('表示表单要提交了...')
event.preventDefault()
})