放大镜案例
法一:
<div class="container" id="glass1">
<div class="left-wraper">
<div class="m-left">
<img src="./image/show_1.jpg" alt="show1" />
<!-- 遮罩层 -->
<div class="mask"></div>
</div>
<ul>
<li class="active"><img src="./image/small_1.jpg" alt="small1" /></li>
<li><img src="./image/small_2.jpg" alt="small2" /></li>
<li><img src="./image/small_3.jpg" alt="small3" /></li>
<li><img src="./image/small_4.jpg" alt="small4" /></li>
</ul>
</div>
<!-- 放大镜 -->
<div class="right-wraper">
<img src="./image/big_1.jpg" alt="big1" />
</div>
</div>
<script src="./js/index.js"></script>
<script>
let glass = new Glass('#glass1')
glass.setScale()
glass.onGlass()
glass.onTab()
</script>
/**
* 放大镜类
*/
class Glass {
constructor(id) {
this.rootEle = document.querySelector(id)
this.mask = this.rootEle.querySelector('.mask') //mask遮罩层
this.showBox = this.rootEle.querySelector('.m-left') //showbox显示盒子
this.glassBox = this.rootEle.querySelector('.right-wraper') // 放大镜glassBox
this.bgPic = this.rootEle.querySelector('.right-wraper>img') //背景图bgpic
this.ulLis = this.rootEle.querySelectorAll('.left-wraper ul>li')
this.showBoxPic = this.showBox.querySelector('img')
}
/**
* 计算放大镜图片的比例
* 目的: 遮罩层区域遮罩区域大小 与 放大镜放大区域大小相同
* 遮罩层mask 放大镜
* -------------- = -----------------
* 显示盒子showBox 背景图 ?
* 背景图 = 放大镜* showBox / mask
*/
setScale() {
// 遮罩层mask
let maskW = parseInt(window.getComputedStyle(this.mask).width)
let maskH = parseInt(window.getComputedStyle(this.mask).height)
// 显示盒子showBox
let showBoxW = parseInt(window.getComputedStyle(this.showBox).width)
let showBoxH = parseInt(window.getComputedStyle(this.showBox).height)
// 放大镜glassBox
let glassBoxW = parseInt(window.getComputedStyle(this.glassBox).width)
let glassBoxH = parseInt(window.getComputedStyle(this.glassBox).height)
// 背景图
let bgPicW = (glassBoxW * showBoxW) / maskW
let bgPicH = (glassBoxH * showBoxH) / maskH
this.bgPic.style.width = bgPicW + 'px'
this.bgPic.style.height = bgPicH + 'px'
}
/**
* 遮罩层移光标移动
* offsetX offsetY 相对自身
* clientX clientY 浏览器
* pageX pageY 页面
*
* window.getComputedStyle(ele).width
* offsetWidth
* clientWidth
*/
onGlass() {
let _this = this
// 移入显示
this.showBox.addEventListener('mouseover',()=>{
this.mask.style.display = 'block'
this.glassBox.style.display = 'block'
})
// 移出隐藏
this.showBox.addEventListener('mouseout',()=>{
this.mask.style.display = 'none'
this.glassBox.style.display = 'none'
})
//showBox鼠标移动事件
this.showBox.addEventListener('mousemove', function (e) {
e = e || window.event
let x = e.offsetX - _this.mask.clientWidth / 2
let y = e.offsetY - _this.mask.clientHeight / 2
// 边界检查
if (x < 0) {
x = 0
}
if (x > _this.showBox.clientWidth - _this.mask.clientWidth) {
x = _this.showBox.clientWidth - _this.mask.clientWidth
}
if (y < 0) {
y = 0
}
if (y > _this.showBox.clientHeight - _this.mask.clientHeight) {
y = _this.showBox.clientHeight - _this.mask.clientHeight
}
// 移动遮罩层
_this.mask.style.left = x + 'px'
_this.mask.style.top = y + 'px'
// 移动背景图片
/*
遮罩层 遮罩层移动距离
------ = -----------------
放大镜 背景图移动距离?
背景图移动距离= 遮罩层移动距离*放大镜/遮罩层
*/
// 遮罩层mask
let maskW = parseInt(window.getComputedStyle(_this.mask).width)
let maskH = parseInt(window.getComputedStyle(_this.mask).height)
// 放大镜glassBox
let glassBoxW = parseInt(window.getComputedStyle(_this.glassBox).width)
let glassBoxH = parseInt(window.getComputedStyle(_this.glassBox).height)
let moveX = x * glassBoxW / maskW
let moveY = y * glassBoxH / maskH
_this.bgPic.style.left = -moveX + 'px'
_this.bgPic.style.top = -moveY + 'px'
})
}
/**
* 切换图片
*/
onTab(){
let _this = this
for(let i = 0; i < this.ulLis.length; i++){
this.ulLis[i].addEventListener('mouseover',function(){
// 清除所有选中效果
_this.onClear()
// 当前选设置选中效果
this.className = 'active'
// 显示盒子图片
_this.showBoxPic.setAttribute('src',`./image/show_${i+1}.jpg`)
// 背景图片切换
_this.bgPic.setAttribute('src',`./image/big_${i+1}.jpg`)
})
}
}
onClear(){
for(let i = 0; i < this.ulLis.length; i++){
this.ulLis[i].className = ''
}
}
}
*{padding: 0;margin: 0;}
ul,li{list-style: none;}
.container{
width: 1000px;
margin: 100px auto;
display: flex;
}
.container .m-left{
position: relative;
width: 350px;
height: 350px;
}
.container .m-left .mask{
width: 200px;
height: 200px;
background-color: rgba(219, 219, 109, 0.6);
position: absolute;
top: 0;
left: 0;
pointer-events: none;
display: none;
}
.container ul{
display: flex;
justify-content:space-around;
}
.container ul .active{
border: 1px solid red;
}
.container .right-wraper{
position: relative;
width: 400px;
height: 400px;
border: 2px solid gray;
overflow: hidden;
margin-left: 20px;
display: none;
}
.container .right-wraper img{
position: absolute;
left: 0;
top: 0;
}
法二
<div class="container" id="glass1">
<div class="left-wraper">
<div class="m-left">
<!-- <img src="./image/show_1.jpg" alt="show1" /> -->
<ol>
<li class="on"><img src="./image/show_1.jpg" alt="show1"></li>
<li><img src="./image/show_2.jpg" alt="show2"></li>
<li><img src="./image/show_3.jpg" alt="show3"></li>
<li><img src="./image/show_4.jpg" alt="show4"></li>
</ol>
<!-- 遮罩层 -->
<div class="mask"></div>
</div>
<ul>
<li class="active"><img src="./image/small_1.jpg" alt="small1" /></li>
<li><img src="./image/small_2.jpg" alt="small2" /></li>
<li><img src="./image/small_3.jpg" alt="small3" /></li>
<li><img src="./image/small_4.jpg" alt="small4" /></li>
</ul>
</div>
<!-- 放大镜 -->
<div class="right-wraper">
<img src="./image/big_1.jpg" alt="big1" />
</div>
</div>
<script src="./js/index.js"></script>
<script>
let glass = new Glass('#glass1')
glass.setScale()
glass.onGlass()
glass.onTab()
</script>
/**
* 放大镜类
*/
class Glass {
constructor(id) {
this.rootEle = document.querySelector(id)
this.mask = this.rootEle.querySelector('.mask') //mask遮罩层
this.showBox = this.rootEle.querySelector('.m-left') //showbox显示盒子
this.glassBox = this.rootEle.querySelector('.right-wraper') // 放大镜glassBox
this.bgPic = this.rootEle.querySelector('.right-wraper>img') //背景图bgpic
this.ulLis = this.rootEle.querySelectorAll('.left-wraper ul>li')
this.olLis = this.rootEle.querySelectorAll('.left-wraper ol>li')
this.showBoxPic = this.showBox.querySelector('img')
}
/**
* 计算放大镜图片的比例
* 目的: 遮罩层区域遮罩区域大小 与 放大镜放大区域大小相同
* 遮罩层mask 放大镜
* -------------- = -----------------
* 显示盒子showBox 背景图 ?
* 背景图 = 放大镜* showBox / mask
*/
setScale() {
// 遮罩层mask
let maskW = parseInt(window.getComputedStyle(this.mask).width)
let maskH = parseInt(window.getComputedStyle(this.mask).height)
// 显示盒子showBox
let showBoxW = parseInt(window.getComputedStyle(this.showBox).width)
let showBoxH = parseInt(window.getComputedStyle(this.showBox).height)
// 放大镜glassBox
let glassBoxW = parseInt(window.getComputedStyle(this.glassBox).width)
let glassBoxH = parseInt(window.getComputedStyle(this.glassBox).height)
// 背景图
let bgPicW = (glassBoxW * showBoxW) / maskW
let bgPicH = (glassBoxH * showBoxH) / maskH
this.bgPic.style.width = bgPicW + 'px'
this.bgPic.style.height = bgPicH + 'px'
}
/**
* 遮罩层移光标移动
* offsetX offsetY 相对自身
* clientX clientY 浏览器
* pageX pageY 页面
*
* window.getComputedStyle(ele).width
* offsetWidth
* clientWidth
*/
onGlass() {
let _this = this
// 移入显示
this.showBox.addEventListener('mouseover',()=>{
this.mask.style.display = 'block'
this.glassBox.style.display = 'block'
})
// 移出隐藏
this.showBox.addEventListener('mouseout',()=>{
this.mask.style.display = 'none'
this.glassBox.style.display = 'none'
})
//showBox鼠标移动事件
this.showBox.addEventListener('mousemove', function (e) {
e = e || window.event
let x = e.offsetX - _this.mask.clientWidth / 2
let y = e.offsetY - _this.mask.clientHeight / 2
// 边界检查
if (x < 0) {
x = 0
}
if (x > _this.showBox.clientWidth - _this.mask.clientWidth) {
x = _this.showBox.clientWidth - _this.mask.clientWidth
}
if (y < 0) {
y = 0
}
if (y > _this.showBox.clientHeight - _this.mask.clientHeight) {
y = _this.showBox.clientHeight - _this.mask.clientHeight
}
// 移动遮罩层
_this.mask.style.left = x + 'px'
_this.mask.style.top = y + 'px'
// 移动背景图片
/*
遮罩层 遮罩层移动距离
------ = -----------------
放大镜 背景图移动距离?
背景图移动距离= 遮罩层移动距离*放大镜/遮罩层
*/
// 遮罩层mask
let maskW = parseInt(window.getComputedStyle(_this.mask).width)
let maskH = parseInt(window.getComputedStyle(_this.mask).height)
// 放大镜glassBox
let glassBoxW = parseInt(window.getComputedStyle(_this.glassBox).width)
let glassBoxH = parseInt(window.getComputedStyle(_this.glassBox).height)
let moveX = x * glassBoxW / maskW
let moveY = y * glassBoxH / maskH
_this.bgPic.style.left = -moveX + 'px'
_this.bgPic.style.top = -moveY + 'px'
})
}
/**
* 切换图片
*/
onTab(){
let _this = this
for(let i = 0; i < this.ulLis.length; i++){
this.ulLis[i].addEventListener('mouseover',function(){
// 清除所有选中效果
_this.onClear()
// 当前选设置选中效果
this.className = 'active'
// 显示盒子图片
_this.olLis[i].className = 'on'
_this.bgPic.setAttribute('src',`./image/big_${i+1}.jpg`)
})
}
}
onClear(){
for(let i = 0; i < this.ulLis.length; i++){
this.ulLis[i].className = ''
this.olLis[i].className = ''
}
}
}
*{padding: 0;margin: 0;}
ul,li{list-style: none;}
.container{
width: 1000px;
margin: 100px auto;
display: flex;
}
.container .m-left{
position: relative;
width: 350px;
height: 350px;
}
.container .m-left ol{
position: relative;
width: 100%;
height: 100%;
}
.container .m-left ol li{
position: absolute;
top: 0;
left: 0;
display: none;
}
.container .m-left ol .on{
display: block;
}
.container .m-left .mask{
width: 200px;
height: 200px;
background-color: rgba(219, 219, 109, 0.6);
position: absolute;
top: 0;
left: 0;
pointer-events: none;
display: none;
}
.container ul{
display: flex;
justify-content:space-around;
}
.container ul .active{
border: 1px solid red;
}
.container .right-wraper{
position: relative;
width: 400px;
height: 400px;
border: 2px solid gray;
overflow: hidden;
margin-left: 20px;
display: none;
}
.container .right-wraper img{
position: absolute;
left: 0;
top: 0;
}
单页应用路由开发
SPA: single Page Appliction
index.html
路由 一个资源切换到另一个资源
login.html -> home.html -> detail.html
hash值
index.html#login -> index.html#home -> index.html#detail
LoginPage HomePage DetailPage
<script type="module">
import { router } from "./js/routes.js";
router() // 初始化调用一次
// 监听hash值变化,重新调用router切换界面
window.addEventListener('hashchange',function(){
router()
})
</script>
/**
* 登录页面
*/
export function createLoginPage() {
let loginPage = `<form>
<p>登录界面</p>
<input type="text" placeholder="请输入用户名" name="username"><br>
<input type="text" placeholder="请输入密码" name="password"><br>
<input type="submit" value="登录" class="btn">
</form>`
let divEle = document.createElement('div')
divEle.setAttribute('class', 'login-wrapper')
divEle.innerHTML = loginPage
// 阻止默认action手动跳转
const formEle = divEle.querySelector('form')
const userInput = divEle.querySelector('input[name="username"]')
const passwordInput = divEle.querySelector('input[name="password"]')
formEle.addEventListener('submit',function(e){
e = e || window.event
e.preventDefault() // 阻止默认行为
// 用户名密码验证
let username = userInput.value
let password = passwordInput.value
if(username == 'admin' && password == '123'){
location.href = './#home'
}else{
alert('用户名或密码出错!')
}
})
return divEle
}
/**
* 主界面
*/
export function createHomePage(){
let homePage = `<h2>商城系统首页 <span><a href="./#login">退出登录</a></span></h2>
<table>
<tr>
<th>商品名称</th>
<th>商品图片</th>
<th>商品价格</th>
<th>商品数量</th>
<th>操作</th>
</tr>
<tr>
<td>javascript高级编程</td>
<td><img src="./image/shoppingBg_03.jpg" alt="pic1"></td>
<td>¥88.9</td>
<td>1</td>
<td><a href="./#detail">查看详情</a></td>
</tr>
<tr>
<td>javascript高级编程</td>
<td><img src="./image/shoppingBg_03.jpg" alt="pic1"></td>
<td>¥88.9</td>
<td>1</td>
<td><a href="./#detail">查看详情</a></td>
</tr>
</table>`
let homeRoot = document.createElement('div')
homeRoot.setAttribute('class','home-wrapper')
homeRoot.innerHTML = homePage
return homeRoot
}
/**
* 详情页
*/
export function createDetailPage(){
let detailPage = `<h2>商品详情 <a href="./#home">首页</a></h2>
<div class="m-detail">
<p><img src="./image/shoppingBg_03.jpg" alt="pic" ></p>
<p>商品名称: javascript高级编程</p>
<p>商品价格: ¥88.9</p>
<p>商品数量: 1</p>
</div>`
let detailRoot = document.createElement('div')
detailRoot.setAttribute('class','detail-wraper')
detailRoot.innerHTML = detailPage
return detailRoot
}
import { createLoginPage, createHomePage, createDetailPage } from './pages.js'
let loginPage = createLoginPage() // 登录界面
let homePage = createHomePage() // 主界面
let detailPage = createDetailPage() // 详情页
/**
* 路由规则表
* hash值:页面
**/
let routes = [
{
url: 'login',
page: loginPage,
},
{
url: 'home',
page: homePage,
},
{
url: 'detail',
page: detailPage,
},
]
// 路由跳转
export function router() {
// #login #home #detail
let url = location.hash.slice(1) // 获取hash值,去掉前面#
url = url || 'login' // 默认登录界面
//根据url查找路由规则表中page节点,添加到body显示
let routesObj = routes.find(item => item.url == url)
let page = routesObj.page
// 先清除原来节点元素
document.body.innerHTML = ''
document.body.appendChild(page)
}
detail.css :
.detail-wraper{
width: 1200px;
margin: 100px auto;
}
.detail-wraper h2{
text-align: center;
}
.detail-wraper .m-detail{
width: 100%;
text-align: center;
}
home.css
a{
text-decoration: none;
color: rgb(71, 70, 70);
}
.home-wrapper{
width: 1200px;
margin: 100px auto;
}
.home-wrapper h2{
text-align: center;
}
.home-wrapper h2 span>a{
font-size: 14px;
}
.home-wrapper table{
width: 100%;
text-align: center;
}
.home-wrapper table tr,td,th{
border-bottom: 1px dotted gray;
}
login.css
* {
padding: 0;
margin: 0;
user-select: none;
}
ul,li{
list-style: none;
}
a{
text-decoration: none;
color: rgb(73, 72, 72);
}
.login-wrapper {
width: 400px;
height: 400px;
border-radius: 25px;
text-align: center;
padding: 5px 40px;
box-sizing: border-box;
background-color: whitesmoke;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.login-wrapper input {
background-color: whitesmoke;
width: 100%;
height: 48px;
margin-bottom: 10px;
border: none;
border-bottom: 2px solid silver;
/* 下面的会覆盖上面的步伐 */
outline: none;
font-size: 22px;
}
.login-wrapper .btn {
background-color: #59c2c5;
width: 38%;
height: 48px;
border-radius: 8px;
margin-top: 40px;
font-size: 24px;
font-weight: 600;
color: white;
}
.login-wrapper .btn:hover {
background-color: #59c2a0;
}
.login-wrapper p {
font-size: 38px;
font-weight: 600;
padding: 40px 0;
}
.main-wraper{
border: 1px solid rgb(199, 195, 195);
width: 1200px;
text-align: center;
margin: 100px auto;
}
.main-wraper ul{
line-height: 40px;
}