首先放下作者大大的github地址:https://github.com/SJanJan/keep-web
接着我们看下项目
//main.js
import Vue from ‘vue‘
import App from ‘./App.vue‘
import ‘@/styles/reset.scss‘
Vue.config.productionTip = false
new Vue({
render: h => h(App)
}).$mount(‘#app‘)
//AppNavbar.vue
<template>
<div class="header">
<nav class="nav-wrapper-phone">
<div style="padding: 22px 5.6%;">
<a href="#"
class="menu">
<img src="@/assets/images/menu.png"
style="width:28px;"
alt="menu">
</a>
<a href="#"
class="logo"> <img style="width:68px;"
src="@/assets/phonelogo.png"
alt="logo">
</a>
</div>
</nav>
<nav class="nav-wrapper-pc">
<a href="#"
class="logo"> <img style="width:112px;"
src="@/assets/logo.png"
alt="logo">
</a>
<div class="head-right">
<a href="#">发现精选</a>
<a href="#">课程内容</a>
</div>
</nav>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.header {
position: relative;
z-index: 2;
width: 100%;
}
.nav-wrapper-phone {
display: none;
position: absolute;
width: 100%;
a > img {
vertical-align: middle;
}
.logo {
position: absolute;
left: 50%;
margin-left: -30px;
}
}
.nav-wrapper-pc {
display: none;
padding: 20px 30px 0;
.head-right {
a {
text-decoration: none;
color: #fff;
}
a + a {
margin-left: 20px;
}
}
}
@media (max-width: 767.98px) {
.nav-wrapper-phone {
display: block;
}
}
@media (min-width: 768px) {
.header {
position: fixed;
}
.nav-wrapper-pc {
display: flex;
justify-content: space-between;
align-items: center;
}
}
</style>
//AppFooter.vue
<template>
<footer>
<div class="footer-wrapper">
<p style="color:#fff;">哪有什么天生如此,只是我们天天坚持
自律给我*</p>
</div>
</footer>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
footer {
position: relative;
background: #584f60;
}
.footer-wrapper {
color: black;
text-align: center;
padding: 100px 0;
}
</style>
//AppContent.vue
<template>
<div class="content-wrap">
<ParagraphContent />
<TrainingContent />
<RunParaContent />
<RunContent />
<CommunityParaContent />
<Community />
<ParagraphStoreContent />
<StoreContent />
<UsersContent />
<LinkContent />
</div>
</template>
<script>
import ParagraphContent from "@/components/ParagraphContent";
import TrainingContent from "@/components/TrainingContent";
import RunParaContent from "@/components/RunParaContent";
import RunContent from "@/components/RunContent";
import CommunityParaContent from "@/components/CommunityParaContent";
import Community from "@/components/Community";
import ParagraphStoreContent from "@/components/ParagraphStoreContent";
import StoreContent from "@/components/StoreContent";
import UsersContent from "@/components/UsersContent";
import LinkContent from "@/components/LinkContent";
export default {
components: {
ParagraphContent,
TrainingContent,
RunParaContent,
RunContent,
CommunityParaContent,
Community,
ParagraphStoreContent,
StoreContent,
UsersContent,
LinkContent,
},
}
</script>
<style lang="scss" scoped>
.content-wrap {
position: relative;
z-index: 2;
background-color: #fff;
}
</style>
//ParagraphContent.vue
<template>
<section>
<div class="paragraph">
<div class="para-title">量体裁衣 & 多种健身训练供你选择</div>
<div class="para-text">训练计划针对不同人群、各种器械和阶段健身目标组合编排,适用最广泛的健身场景。</div>
</div>
</section>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.paragraph {
padding: 54px 0;
text-align: center;/* */
.para-title {
font-size: 18px;
color: #584f60;
font-weight: bold;
}
.para-text {
font-size: 14px;
color: #666;
margin: 19px 48px 0;
}
}
@media (min-width: 768px) {
.paragraph {
padding: 130px 0 140px;
.para-title {
font-size: 24px;
}
.para-text {
margin-top: 32px;
font-size: 18px;
}
}
}
</style>
//TrainingContent.vue
<template>
<section class="container">
<div class="training-wrap">
<div class="training-wrap-inner">
<div class="training-block">
<a href="#"
class="training-item"
:style="{backgroundImage:‘url(‘+bg1+‘)‘ }">
<div class="training-detail">
<div class="training-title">瘦腿训练</div>
<div>13分钟 49千卡</div>
<div class="training-population">48,385,041人训练</div>
</div>
</a>
<a href="#"
class="training-item"
:style="{backgroundImage:‘url(‘+bg2+‘)‘ }">
<div class="training-detail">
<div class="training-title">马甲线养成</div>
<div>12分钟 61千卡</div>
<div class="training-population">49,252,615人训练</div>
</div>
</a>
<a href="#"
class="training-item"
:style="{backgroundImage:‘url(‘+bg3+‘)‘ }">
<div class="training-detail">
<div class="training-title">瑜伽 · 身体韵律</div>
<div>32分钟 135千卡</div>
<div class="training-population">928,978人训练</div>
</div>
</a>
<a href="#"
class="training-item"
:style="{backgroundImage:‘url(‘+bg4+‘)‘ }">
<div class="training-detail">
<div class="training-title">地狱Burpees挑战</div>
<div>13分钟 191千卡</div>
<div class="training-population">1,247,907人训练</div>
</div>
</a>
</div>
<div class="training-text">
<div class="text-title">真人同步训练记录训练进度</div>
<div class="text-cont">全程语音督导,自动同步进度,不需要背动作、记组数,跟着 Keep 马上练起来。</div>
<a href="#"
class="training-btn"><span>查看课程</span></a>
</div>
<div class="training-data">
<div class="data-text">
<span class="text-line"></span>
<span>累积训练:</span>
</div>
<div class="data-time">
<span class="data-min">68.79</span>
<span class="data-text data-unit">亿分钟</span>
</div>
<div class="data-cont">
<span>
<span class="data-num">4.93</span>
<span class="data-text data-unit">亿次</span>
</span>
<span>
<span class="data-num data-cal">388.56</span>
<span class="data-text data-unit">亿千卡</span>
</span>
</div>
</div>
<div class="body-pic-wrap">
<img src="@/assets/images/body.png"
class="body-pic">
<img src="@/assets/images/bodycircle.png"
class="circle-pic">
<img src="@/assets/images/heart.png"
class="animate-heart">
</div>
<img src="@/assets/images/traindata.png"
class="data-pic">
<img src="@/assets/images/trainchart.png"
class="chart-pic">
<img src="@/assets/images/trainpic.png"
class="cal-pic">
</div>
</div>
</section>
</template>
<script>
import bg1 from "@/assets/images/1478591073270_750x700.jpg";
import bg2 from "@/assets/images/1478588565783_750x700.jpg";
import bg3 from "@/assets/images/1488452269169_750x700.jpg";
import bg4 from "@/assets/images/54cc47743b800000.jpg";
export default {
data () {
return {
bg1: bg1,
bg2: bg2,
bg3: bg3,
bg4: bg4,
}
},
}
</script>
<style lang="scss" scoped>
.container {
background: #3d3744;
}
.training-wrap {
max-width: 1440px;
margin: 0 auto;
}
.training-item {
display: block;
margin: 0;
width: 100%;
height: 222px;
position: relative;
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
transition: all 0.5s;
&:hover {
transform: scale(1.05, 1.05);
}
&:last-child {
display: none;
}
}
.training-detail {
display: block;
position: relative;
height: 100%;
font-size: 14px;
padding: 22px;
}
.training-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
}
.training-population {
position: absolute;
bottom: 22px;
}
.training-text {
margin-top: 120px;
text-align: center;
.text-title {
font-size: 18px;
}
.text-cont {
font-size: 12px;
margin: 18px 33px 28px;
color: #999;
}
.training-btn {
cursor: pointer;
display: inline-block;
width: 138px;
height: 40px;
line-height: 40px;
margin-bottom: 60px;
text-align: center;
border: 1px solid #8e8893;
border-radius: 40px;
font-size: 14px;
}
}
a {
text-decoration: none;
color: #fff;
}
.training-data,
.body-pic-wrap,
.data-pic,
.chart-pic,
.cal-pic {
display: none;
}
.body-pic-wrap {
position: absolute;
left: calc(50% - 170px);
width: 340px;
height: 538px;
.body-pic {
position: absolute;
top: 0;
left: 73px;
}
.circle-pic {
position: absolute;
left: 0;
bottom: 0;
}
.animate-heart {
position: absolute;
top: 104px;
left: 188px;
animation: heartbeat 2s ease infinite normal;
}
}
.training-data {
line-height: 1;
span {
display: inline-block;
}
.data-text {
font-size: 12px;
color: #8e8893;
.text-line {
height: 10px;
border: 2px solid #25c085;
margin-right: 5px;
}
}
.data-time {
margin: 16px 0 0;
.data-min {
font-size: 44px;
font-weight: 700;
}
.data-unit {
margin-left: 8px;
}
}
.data-cont {
margin: 32px 0 0;
.data-num {
font-size: 26px;
font-weight: 600;
}
.data-unit {
margin-left: 8px;
}
.data-cal {
margin-left: 32px;
}
}
}
@media (min-width: 750px) {
.training-item {
&:last-child {
display: inline-block;
}
}
}
@media (max-width: 1023px) and (min-width: 768px) {
.training-wrap {
height: 1050px;
position: relative;
}
.training-block {
position: relative;
width: 740px;
left: 50%;
margin-left: -370px;
top: -45px;
}
.training-item {
display: inline-block;
width: 356px;
margin-bottom: 10px;
margin-right: 10px;
}
.training-text {
position: absolute;
right: 23px;
bottom: 0;
width: 265px;
margin: 0;
text-align: right;
.text-cont {
font-size: 14px;
margin: 14px 0 22px;
}
}
.training-data {
display: block;
position: absolute;
left: 23px;
bottom: 60px;
}
.body-pic-wrap {
display: block;
}
.data-pic {
display: block;
position: absolute;
top: 498px;
right: 96px;
}
.chart-pic {
display: block;
position: absolute;
top: 498px;
left: 25px;
}
}
@media (min-width: 1024px) {
.training-wrap {
position: relative;
height: 636px;
.training-wrap-inner {
height: 636px;
}
}
.training-block {
width: 356px;
position: relative;
left: 30px;
top: -15px;
.training-item + .training-item {
margin: 10px 0 0;
}
.training-item {
display: block;
width: 356px;
height: 207px;
&:last-child {
display: none;
}
}
}
.body-pic-wrap {
display: block;
position: absolute;
top: 70px;
left: calc(50% - 120px);
}
.training-text {
position: absolute;
right: 23px;
bottom: 40px;
width: 265px;
margin: 0;
text-align: right;
.text-cont {
font-size: 14px;
margin: 14px 0 22px;
}
.training-btn {
margin: 0;
}
}
.training-data {
display: block;
position: absolute;
right: 25px;
top: 260px;
text-align: right;
.data-cont {
margin-top: 22px;
}
.data-unit {
display: block;
margin-top: 12px;
}
}
.data-pic {
display: block;
position: absolute;
top: 40px;
right: 160px;
}
.cal-pic {
display: block;
position: absolute;
right: 27px;
top: 140px;
}
}
@media (min-width: 1440px) {
.body-pic-wrap {
left: calc(50% - 30px);
}
.chart-pic {
display: block;
position: absolute;
top: 35px;
left: 430px;
}
.cal-pic {
display: block;
position: absolute;
top: 305px;
left: 446px;
}
.training-data {
display: block;
position: absolute;
top: initial;
left: 445px;
bottom: 53px;
right: initial;
text-align: left;
.data-unit {
display: inline-block;
}
}
}
@keyframes heartbeat {
from {
transform: scale(1);
opacity: 1;
}
to {
transform: scale(3);
opacity: 0;
}
}
</style>
//RunParaContent.vue
<template>
<section>
<div class="paragraph run-para">
<div class="para-title">户外跑步 & 精准跑步记录,让你的跑步更加系统</div>
<div class="para-text">精准跑步路线记录,跑前热身与跑后拉伸,Keep 提供更加完善和专业的跑步指导。</div>
</div>
</section>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.paragraph {
text-align: center;
}
.para-title {
color: #584f60;
font-weight: bold;
}
.para-text {
color: #666;
}
@media (max-width: 767px) {
.paragraph.run-para {
padding: 72px 0 250px;
}
.para-title {
font-size: 21px;
padding: 0 27.6px;
}
.para-text {
font-size: 14px;
margin: 19.2px 48px 0;
}
}
@media (min-width: 768px) {
.paragraph {
padding: 130px 0 140px;
}
.para-title {
font-size: 24px;
}
.para-text {
font-size: 16px;
margin-top: 32px;
}
}
</style>
//RunContent.vue
<template>
<section>
<div class="run-wrap">
<div class="run-wrap-inner">
<div class="run-track-wrap">
<img src="@/assets/images/runtrack.png">
<div class="animate-circle"></div>
</div>
<div class="run-config-wrap">
<div class="run-config-pace">
<div class="config-title"><i class="keep-icon-speed"></i><span>配速</span></div>
<div class="config-cont"><span>公里</span><span>配速</span><span class="right">用时</span></div>
<div class="speed-bar speed-bar1">
<div class="speed-bar-fill"></div>
</div>
<div class="speed-bar speed-bar2">
<div class="speed-bar-fill"></div>
</div>
<div class="speed-bar speed-bar3">
<div class="speed-bar-fill"></div>
</div>
<div class="speed-bar speed-bar4">
<div class="speed-bar-fill"></div>
</div>
<div class="speed-bar speed-bar5">
<div class="speed-bar-fill"></div>
</div>
<div class="speed-bar speed-bar6">
<div class="speed-bar-fill"></div>
</div>
<div class="speed-bar speed-bar7">
<div class="speed-bar-fill"></div>
</div>
</div>
<div class="run-config-frequency">
<div class="config-title">
<div>
<i class="keep-icon-frequency"></i>
<span>步频</span>
<span class="right">(步/分钟)</span>
</div>
<div class="chart-title">平均步频<span>146</span></div>
</div>
<!-- <img src="https://staticweb.keepcdn.com/staticShow/images/homepage/runchart-ae8422d700.png"
class="config-bg"> -->
<div id="freq-img"><img src="@/assets/images/runcover.png"></div>
</div>
</div>
<div class="run-text-wrap">
<div class="run-text-title">用步伐丈量世界</div>
<div class="run-text-cont">在 Keep 记录你的跑步轨迹,制定有氧课程表,助你更快达成你的跑步目标</div>
<a href="#"
class="run-btn"><span>跑步轨迹</span><i></i></a>
</div>
<div class="run-data">
<div class="data-block">
<div class="data-title"><span class="text-line"></span><span>累计跑步</span></div>
<div class="data-val">8415.57</div>
<div class="data-unit">万公里</div>
</div>
<div class="data-block-right">
<div class="data-block2">
<div class="data-title"><i class="icon-speed"></i></div>
<div class="data-val">9.27</div>
<div class="data-unit">分/公里</div>
</div>
<div class="data-block2">
<div class="data-title"><i class="icon-duration"></i></div>
<div class="data-val">7.80</div>
<div class="data-unit">亿分钟</div>
</div>
<div class="data-block2">
<div class="data-title"><i class="icon-cal"></i></div>
<div class="data-val">62.05</div>
<div class="data-unit">亿千卡</div>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.run-wrap {
width: 100%;
height: 763.19px;
position: relative;
background-color: #3d3744;
background-image: url(../assets/images/runbg.jpg);
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
}
.run-wrap-inner {
position: relative;
height: 100%;
max-width: 1440px;
margin: 0 auto;
}
.run-config-wrap {
width: 360px;
position: absolute;
top: -182.4px;
right: 50%;
margin-right: -180px;
.run-config-pace {
height: 319.2px;
padding: 22px 18px 20px;
background-color: #5e5566;
border-radius: 5px;
font-size: 12px;
.config-title {
color: #dddddd;
}
.config-cont {
color: #827a89;
margin: 24px 0 12px;
span:first-child {
margin-right: 20px;
}
.right {
float: right;
}
}
.speed-bar {
height: 21.6px;
border-radius: 21.6px;
margin-top: 9.6px;
background-color: rgba(36, 199, 137, 0.3);
}
.speed-bar1 {
width: 54.6%;
}
.speed-bar2 {
width: 42%;
}
.speed-bar3 {
width: 45.4%;
}
.speed-bar4 {
width: 100%;
}
.speed-bar5 {
width: 48.9%;
}
.speed-bar6 {
width: 45.4%;
}
.speed-bar7 {
width: 50.6%;
}
}
.run-config-frequency {
position: relative;
width: 100%;
height: 319.19px;
margin-top: 10px;
.config-title {
width: 100%;
padding: 0 18px;
position: absolute;
top: 22px;
left: 0;
div {
font-size: 12px;
color: #ddd;
.right {
float: right;
color: #827a89;
}
}
.chart-title {
text-align: center;
margin-top: 20px;
span {
margin-left: 5px;
color: #24c789;
}
}
}
#freq-img {
img {
width: 100%;
height: 100%;
}
}
}
}
.run-text-wrap {
width: 100%;
position: absolute;
bottom: 60px;
text-align: center;
.run-text-title {
color: #fff;
font-size: 18px;
}
.run-text-cont {
font-size: 12px;
color: #999999;
margin: 21.6px 39.6px 33.6px;
}
.run-btn {
display: inline-block;
color: #fefefe;
background-color: #24c789;
width: 138px;
height: 42px;
line-height: 42px;
text-align: center;
border-radius: 42px;
font-size: 14px;
box-shadow: 0 4px 16px 0 rgba(32, 178, 122, 0.27);
text-decoration: none;
}
}
.run-data,
.run-track-wrap,
.data-block-right {
display: none;
}
@media (min-width: 768px) {
.run-wrap {
height: 636px;
}
.run-text-wrap {
width: 268px;
top: 45px;
right: 27px;
bottom: initial;
text-align: right;
.run-text-cont {
margin: 20px 0;
}
}
.run-config-wrap {
width: 700px;
top: initial;
bottom: -80px;
right: 50%;
margin-right: -350px;
.run-config-pace,
.run-config-frequency {
float: left;
width: 340px;
height: 302px;
}
.run-config-frequency {
margin-top: initial;
margin-left: 10px;
#freq-img {
margin-bottom: 0;
img {
height: 100%;
}
}
}
}
.run-data {
display: block;
position: absolute;
left: 40px;
bottom: 255px;
.data-block {
.data-title {
font-size: 12px;
color: #8e8893;
.text-line {
display: inline-block;
height: 10px;
border: 2px solid #25c085;
margin-right: 7px;
}
}
.data-val {
display: inline-block;
font-size: 44px;
color: #ddd;
line-height: 1;
margin: 16px 0;
font-weight: bold;
}
.data-unit {
display: inline-block;
margin-left: 12px;
font-size: 12px;
color: #8e8893;
}
}
}
.run-track-wrap {
display: block;
position: absolute;
left: 20%;
top: 115px;
.animate-circle {
width: 60px;
height: 60px;
position: absolute;
bottom: -8px;
right: -12px;
border-radius: 50%;
background: #fff;
animation: scale 2s ease infinite normal;
}
}
}
@media (min-width: 1024px) {
.run-config-wrap {
top: -26px;
right: 28px;
bottom: initial;
width: 384px;
height: 694px;
margin-right: initial;
.run-config-pace,
.run-config-frequency {
float: none;
width: 384px;
height: 342px;
}
.run-config-frequency {
margin-top: 10px;
margin-left: initial;
}
}
.run-text-wrap {
top: 46px;
left: 298px;
right: initial;
}
.run-track-wrap {
left: 45px;
}
.run-data {
right: initial;
left: 44px;
bottom: 44px;
.data-block {
display: inline-block;
}
.data-block-right {
display: inline-block;
margin-left: 120px;
.data-block2 {
display: inline-block;
margin: 0 30px;
text-align: center;
.data-val {
color: #fff;
font-size: 27px;
line-height: 1;
margin: 16px 0;
font-weight: bold;
}
.data-unit {
font-size: 12px;
color: #8e8893;
}
}
}
}
}
@keyframes scale {
0% {
transform: scale(1);
opacity: 0.3;
}
100% {
transform: scale(2);
opacity: 0;
}
}
</style>
//CommunityParaContent.vue
<template>
<section>
<div class="paragraph community-para">
<div class="para-title">运动社区 & 分享健身成果,一起进步</div>
<div class="para-text">拍照记录每一天的变化,分享好友相互勉励,在 Keep 健身不再是孤独的坚持。</div>
</div>
</section>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.paragraph {
text-align: center;
padding: 54px 0;
.para-title {
font-size: 18px;
color: #584f60;
font-weight: bold;
}
.para-text {
font-size: 13.6px;
color: #666;
margin: 19.2px 48px 0;
}
}
@media (min-width: 768px) {
.paragraph {
padding: 180px 0 100px;
.para-title {
font-size: 24px;
}
.para-text {
font-size: 16px;
margin: 30px 0 0;
}
}
}
@media (min-width: 1024px) {
.paragraph {
padding: 130px 0 140px;
}
}
</style>
//Community.vue
<template>
<section>
<div class="community-wrap">
<img src="@/assets/images/camera.png"
class="camera-pic">
<div class="community-text">
<div class="text-title">千万用户伴你训练</div>
<div class="text-cont">Keep 希望创造一个专业、有趣的健身社区,在这里你会找到渴望共同进步的小伙伴。</div>
<a href="#"
class="text-btn">
<span>社区精选</span><i></i>
</a>
</div>
</div>
</section>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.community-wrap {
position: relative;
height: 763.19px;
padding: 0;
background-color: #3d3744;
background-image: url(../assets/images/communitybg-sm.jpg);
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
}
.camera-pic {
position: absolute;
left: 50%;
bottom: 0;
margin-left: -154px;
}
.community-text {
position: absolute;
top: 197px;
left: 50%;
margin-left: -135px;
width: 284px;
text-align: center;
.text-title {
font-size: 16px;
color: #ffffff;
}
.text-cont {
color: #8e8893;
font-size: 14px;
margin: 14px 0 22px;
}
.text-btn {
display: inline-block;
width: 138px;
height: 42px;
line-height: 42px;
text-align: center;
background: #584f60;
border-radius: 42px 42px;
font-size: 14px;
color: #ddd;
text-decoration: none;
}
}
@media (min-width: 768px) {
.community-wrap {
height: 636px;
background: #3d3744;
}
}
</style>
//ParagraphStoreContent.vue
<template>
<section>
<div class="paragraph">
<div class="para-title">品牌装备 & 商城,伴你尽兴挥汗</div>
<div class="para-text">Keep 品牌服饰、器械及智能装备,打破 App 边界成为你触手可及的运动伙伴。</div>
</div>
</section>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.paragraph {
padding: 54px 0;
text-align: center;
.para-title {
font-size: 18px;
font-weight: bold;
color: #584f60;
margin: 0 27.6px;
}
.para-text {
font-size: 13.6px;
color: #666666;
margin: 19.2px 48px 0;
}
}
@media (min-width: 768px) {
.paragraph {
padding: 130px 0 140px;
.para-title {
font-size: 24px;
}
.para-text {
font-size: 16px;
margin: 32px 0 0;
}
}
}
</style>
//StoreContent.vue
<template>
<section>
<div class="store-wrap">
<div class="store-wrap-inner">
<img src="@/assets/images/store-bg320.jpg"
class="store-bg-pic">
<div class="store-goods"></div>
<div class="store-goods-text">更多智能运动产品 持续推出中</div>
<div class="store-keleton"></div>
<div class="store-text">
<div class="store-title">Keep 跑步机</div>
<div class="store-subtitle">跟 着 跑 就 对 了</div>
<div class="store-cont">科技互联的运动新装备<br>专注于家庭与个人的运动新体验<br>带给你有效果的运动方式</div>
<div class="store-btn-wrap"><a href="https://mo.gotokeep.com/pc/mall"
target="_blank"
class="store-btn"><span>查看更多</span><i></i></a></div>
</div>
</div>
</div>
</section>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.store-wrap-inner {
position: relative;
height: 100%;
margin: 0 auto;
}
.store-bg-pic {
display: block;
width: 100%;
}
.store-text {
position: absolute;
top: initial;
right: initial;
left: 50%;
transform: translate(-50%, 0);
bottom: 31.4%;
text-align: center;
.store-title {
font-size: 18px;
}
.store-subtitle {
font-size: 12px;
margin: 12px 0;
}
.store-cont {
font-size: 12px;
color: #999999;
margin: 21.6px 0 31.6px;
}
.store-btn {
display: inline-block;
width: 138px;
height: 42px;
line-height: 42px;
text-align: center;
background: #584f60;
border-radius: 42px 42px;
font-size: 14px;
color: #ddd;
text-decoration: none;
}
}
.store-goods-text {
display: none;
}
@media (min-width: 768px) {
.store-wrap {
position: relative;
height: 636px;
background-color: #3d3744;
background-image: url(../assets/images/storebg.jpg);
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
}
.store-bg-pic {
display: none;
}
.store-goods {
position: absolute;
left: 50%;
margin-left: -349px;
top: initial;
bottom: 38px;
width: 698px;
height: 180px;
background-image: url(../assets/images/store-goods768.png);
}
.store-keleton {
position: absolute;
right: initial;
left: -2%;
bottom: 180px;
width: 583px;
height: 419px;
background-image: url(../assets/images/store-keleton768.png);
}
.store-text {
top: 90px;
left: initial;
bottom: initial;
right: 26px;
transform: none;
text-align: right;
.store-title {
font-size: 14px;
}
.store-subtitle {
font-size: 18px;
}
.store-cont {
font-size: 14px;
line-height: 1.6;
margin: 15px 0 35px;
}
}
}
@media (min-width: 1024px) {
.store-goods {
left: 28px;
top: 42px;
margin: initial;
width: 355px;
height: 506px;
background-image: url(../assets/images/store-goods1024.png);
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
}
.store-keleton {
position: absolute;
right: 0;
left: initial;
bottom: -20px;
width: 700px;
height: 500px;
background-image: url(../assets/images/store-keleton1024.png);
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
}
.store-goods-text {
display: block;
position: absolute;
bottom: 38px;
left: 28px;
color: #8e8893;
font-size: 14px;
}
}
@media (min-width: 1440px) {
.store-wrap-inner {
width: 1200px;
}
}
</style>
接下来这个就很有意思了,用来处理了自动向上滚动和消失的
//UsersContent.vue
<template>
<section class="users-wrap">
<div class="users-wrap-inner">
<div class="users-text">
<div class="users-title">
<div class="icon-qoute"></div>
<div>此刻在 Keep 运动</div>
</div>
<div class="users-cont">每分每秒,都有来自全世界的 Keepers 在这里留下他们的汗水。</div>
</div>
<div class="user-list-wrap">
<ul class="users-list"
ref="usersList"
:class="{move:isMove}">
<li v-for="(item) in list"
:key="item.username">
<a href="#"
target="_blank">
<img :src="item.img">
<div class="user-info">
<div class="user-name">{{item.username}}</div>
<div class="user-act">{{item.userAct}}</div>
</div>
</a>
</li>
</ul>
</div>
</div>
</section>
</template>
<script>
import userAvatar from "@/assets/images/userAvatar.jpg";
const USERS = [
{
img: userAvatar,
username: ‘左小立1‘,
userAct: ‘刚做完了一组 全身拉伸‘,
},
{
img: userAvatar,
username: ‘左小立2‘,
userAct: ‘刚做完了一组 全身拉伸‘,
},
{
img: userAvatar,
username: ‘左小立3‘,
userAct: ‘刚做完了一组 全身拉伸‘,
},
{
img: userAvatar,
username: ‘左小立4‘,
userAct: ‘刚做完了一组 全身拉伸‘,
},
{
img: userAvatar,
username: ‘左小立5‘,
userAct: ‘刚做完了一组 全身拉伸‘,
},
{
img: userAvatar,
username: ‘左小立6‘,
userAct: ‘刚做完了一组 全身拉伸‘,
},
{
img: userAvatar,
username: ‘左小立7‘,
userAct: ‘刚做完了一组 全身拉伸‘,
},
{
img: userAvatar,
username: ‘左小立8‘,
userAct: ‘刚做完了一组 全身拉伸‘,
}
]
export default {
data () {
return {
isMove: false,
list: [...USERS],
nextNum: 0
}
},
mounted () {
this.run();
},
methods: {
async run () {
await this.fadeout();
await this.move()
await this.pop()
await this.push();
this.run();
},
fadeout () {
return new Promise((resolve) => {
this.$refs[‘usersList‘].firstElementChild.classList.add(‘fadeout‘);
setTimeout(() => {
resolve();
}, 1000);
})
},
move () {
return new Promise((resolve) => {
this.isMove = true;
setTimeout(() => {
this.isMove = false;
resolve();
}, 1000);
})
},
// 始终往数组末尾添加被删除的首个元素
push: function () {
let length = USERS.length;
let item = USERS[this.nextNum % length];
this.list.splice(this.list.length, 0, item)
this.nextNum++
if (this.nextNum > length - 1) this.nextNum = 0;
return this.$nextTick()
},
// 移除首个元素
pop: function () {
this.list.splice(0, 1)
return this.$nextTick()
},
},
}
</script>
<style lang="scss" scoped>
.users-wrap {
height: 696px;
}
.users-wrap-inner {
position: relative;
height: 100%;
}
.users-text {
position: absolute;
width: 100%;
top: 80px;
text-align: center;
.users-title {
font-size: 18px;
color: #584f60;
}
.users-cont {
font-size: 12px;
color: #999999;
margin: 24px;
}
}
.user-list-wrap {
position: absolute;
width: 100%;
height: 380px;
overflow: hidden;
top: 300px;
.users-list {
position: relative;
margin: 0 auto;
width: 240px;
li + li {
margin-top: 28px;
}
img {
display: block;
float: left;
width: 36px;
height: 36px;
margin-top: 3px;
border-radius: 50%;
}
.user-info {
margin-left: 56px;
.user-name {
font-size: 12px;
color: #999;
}
.user-act {
font-size: 14px;
color: #584f60;
}
}
}
}
@media (min-width: 768px) {
.users-wrap {
height: 560px;
}
.users-text {
width: 270px;
left: 100px;
top: 104px;
text-align: left;
.users-title {
font-size: 24px;
font-weight: bold;
margin-bottom: 22px;
}
.users-cont {
margin: 0;
}
}
.user-list-wrap {
right: 126px;
top: 104px;
width: 280px;
}
}
.fadeout {
animation: fadeout 1s ease;
animation-fill-mode: forwards;
}
.move {
animation: move 1s ease;
}
@keyframes move {
from {
transform: translateY(0);
}
to {
transform: translateY(-64px);
}
}
@keyframes fadeout {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
a {
text-decoration: none;
}
</style>
//LinkContent.vue
<template>
<section class="link-wrap">
<div class="link-wrap-inner">
<img src="@/assets/images/apppages.png"
class="apppages">
<img src="@/assets/images/qrcode.png"
class="qrcode">
<div class="download-app-wrap">
<p>荣获 App Store 2015 年度精选<br>App Store 官方推荐的移动健身工具</p>
<div class="link-btn-wrap">
<a href="#">
<img src="@/assets/images/appledownload.png">
</a>
<div class="link-text"> 适用于 Apple Watch</div>
</div>
<div class="link-btn-wrap">
<a href="#">
<img src="@/assets/images/androiddownload.png">
</a>
<div class="link-text"> TV 版可在电视应用市场下载</div>
</div>
</div>
</div>
</section>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.link-wrap {
position: relative;
height: 441.59px;
background-image: url(../assets/images/linkbg.jpg);
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
}
.link-wrap-inner {
position: relative;
width: 100%;
height: 100%;
max-width: 1440px;
margin: 0 auto;
}
.download-app-wrap {
position: absolute;
top: 60px;
width: 100%;
p {
text-align: center;
line-height: 2;
font-size: 16px;
color: #fff;
margin: 12px 0 27.6px;
}
.link-btn-wrap {
width: 192px;
margin-top: 24px;
text-align: center;
margin: 24px auto 0;
a {
display: block;
width: 100%;
height: 58px;
img {
width: 100%;
height: 100%;
}
}
.link-text {
margin-top: 7.2px;
font-size: 12px;
}
}
}
.apppages,
.qrcode {
display: none;
}
@media (min-width: 768px) {
.link-wrap {
height: 368px;
}
.download-app-wrap {
text-align: center;
p {
margin-bottom: 36px;
}
.link-btn-wrap {
display: inline-block;
margin-top: initial;
}
.link-btn-wrap + .link-btn-wrap {
margin-left: 20px;
}
}
}
@media (min-width: 1024px) {
.apppages {
display: block;
position: absolute;
left: 72px;
top: -49px;
}
.download-app-wrap {
position: absolute;
top: 65px;
right: 72px;
width: 354px;
text-align: right;
p {
text-align: right;
margin-bottom: 60px;
}
.link-btn-wrap {
width: 156px;
a {
height: 47px;
}
}
}
}
@media (min-width: 1300px) {
.qrcode {
display: block;
position: absolute;
width: 140px;
height: 140px;
right: 606px;
top: 170px;
}
}
</style>
接下来就是重头戏,视频播放那里了
这个地方的处理也是很有技巧的
这个方法还直接获取了更深一级的属性
这个可以理解为视频外面的海报
//AppHeader.vue
<template>
<div>
<header class="keep-header">
<div class="phone-download-warp">
<div class="phone-download">
<p class="phone-title"
style="font-size:24px;font-weight:bold">Keep ? 自律给我*</p>
<p class="phone-cont"
style="font-size:14px;margin-bottom:40px;">一站式解决你所有的运动需求</p>
<a class="phone-link"
href="#"><img src="@/assets/images/appledownload.png"
alt=""></a>
<a class="phone-link"
href="#"><img src="@/assets/images/androiddownload.png"
alt=""></a>
</div>
</div>
<div class="video-wrap">
<video id="video-bg"
src="@/assets/mp4/5s.mp4"
muted
autoplay
loop></video>
<div class="video-control">
<img src="@/assets/images/slogan.png">
<img @click="$emit(‘playVideo‘)"
id="video-play"
src="@/assets/images/play.png">
</div>
<div class="video-bottom">
<div class="bottom-left">
Keep ? 自律给我*
<br>
<br>
一站式解决你所有的运动需求
</div>
<div class="bottom-right">
<a href="#"><img src="@/assets/images/appledownload.png"
alt=""></a>
<a href="#"><img src="@/assets/images/androiddownload.png"
alt=""></a>
<a href="javascript:;"
class="qrcode"><span></span><img src="@/assets/images/qrcode.png"
class="qrcode"></a>
</div>
</div>
</div>
</header>
<div class="filling"></div>
</div>
</template>
<script>
export default {}
</script>
<style lang="scss" scoped>
.keep-header {
width: 100%;
}
.phone-download {
text-align: center;
padding: 35% 0 18%;
.phone-link {
display: block;
width: 170px;
margin: 26px auto 0;
img {
display: block;
width: 100%;
height: 100%;
}
}
}
.phone-download-warp {
display: none;
width: 100%;
height: 100%;
background-image: url("../assets/images/head-1.jpg");
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
}
@media (max-width: 767.98px) {
.phone-download-warp {
display: block;
}
.video-wrap {
display: none;
}
}
@media (min-width: 768px) {
.keep-header {
position: fixed;
width: 100%;
height: calc(49.6vw);
left: 0;
top: 0;
}
.video-wrap {
display: block;
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
.video-control {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(34, 34, 34, 0.8);
#video-play {
display: none;
}
}
.video-bottom {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
position: absolute;
bottom: 30px;
line-height: 1;
.bottom-left {
margin-left: 35px;
}
.bottom-right {
margin-right: 35px;
a + a {
margin-left: 15px;
}
a > img {
width: 160px;
}
a.qrcode {
display: none;
}
}
}
}
#video-bg {
width: 100%;
margin-top: -42px;
object-fit: contain;
}
.filling {
height: calc(49.6vw);
}
}
@media (min-width: 1024px) {
.video-wrap .video-control #video-play {
display: block;
cursor: pointer;
}
.bottom-right {
display: flex;
align-items: center;
a.qrcode {
display: inline-flex !important;
justify-content: center;
align-items: center;
text-align: center;
width: 62px;
height: 50px;
position: relative;
border: 1px solid #fff;
background: transparent;
border-radius: 5px 5px;
span {
display: inline-block;
width: 26px;
height: 26px;
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAAM1BMVEUAAAD///////////////////////////////////////////////////////////////+3leKCAAAAEHRSTlMA3cO7mfDSeKeP9+/QydtIakY+VAAAAIZJREFUKM+VkksOgCAMRKtFqX/uf1qRWmscI/EtWPBIMxlK3ChCRNLcmKlPSptVm250WU3MPL0qvSxnDMbyVE6sqjHHGYsSy2YKEnanCqwMqC48YX61HecHPhDwGD869IGonKJW6xCVWFE4UCgyByhKlaTUQ72g7FNgIKoCKg9fXRsF1ceK7rjBEHokzscQAAAAAElFTkSuQmCC")
no-repeat center center;
background-size: 26px 26px;
color: #fff;
}
&:hover {
img.qrcode {
display: block;
}
}
}
img.qrcode {
display: none;
position: absolute;
right: 0;
bottom: 60px;
}
}
}
</style>
子组件给父组件传递了事件,然后又通过事件去根据值处理播放,项目最核心的地方就是这里了
//VideoPlay.vue
<template>
<div class="video-container"
v-if="visible">
<svg t="1571816192757"
@click="close"
class="close-icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="2452"
width="24"
height="24">
<path d="M559.5392 512l250.1888-250.1888a32.6912 32.6912 0 0 0 0-46.0544l-1.3824-1.3568a32.6912 32.6912 0 0 0-46.0544 0l-250.1632 250.4704-250.1888-250.5984a32.6912 32.6912 0 0 0-46.0544 0l-1.3568 1.3824a32.128 32.128 0 0 0 0 46.0544l250.1632 250.2656-250.1632 250.1888a32.6912 32.6912 0 0 0 0 46.0544l1.3568 1.3568a32.6912 32.6912 0 0 0 46.08 0l250.1632-250.1632 250.1632 250.1632a32.6912 32.6912 0 0 0 46.0544 0l1.3824-1.3568a32.6912 32.6912 0 0 0 0-46.0544l-250.1888-250.1888z"
fill="#999999"
p-id="2453"></path>
</svg>
<video id="video-large"
style="width: 100%;height: 100%;object-fit: contain;"
autoplay
src="@/assets/mp4/full.mp4"
controls></video>
</div>
</template>
<script>
export default {
data () {
return {
visible: false
}
},
methods: {
show () {
this.visible = true;
},
close () {
this.visible = false;
}
},
}
</script>
<style lang="scss" scoped>
.video-container {
position: absolute;
z-index: 200;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #fff;
}
.close-icon {
position: absolute;
z-index: 200;
top: 30px;
right: 30px;
cursor: pointer;
}
</style>
感谢作者大大给我们开源项目,感恩,感谢