用鼠标改变元素的尺寸。
如需了解更多有关 resizable 交互的细节,请查看 API 文档 可调整尺寸小部件(Resizable Widget)。
默认功能
在任意的 DOM 元素上启用 resizable 功能。通过鼠标拖拽右边或底边的边框到所需的宽度或高度。
<!doctype html><html lang="en"><head>
<meta charset="utf-8">
<title>jQuery UI 缩放(Resizable) - 默认功能</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://jqueryui.com/resources/demos/style.css">
<style>
#resizable { width: 150px; height: 150px; padding: 0.5em; }
#resizable h3 { text-align: center; margin: 0; }
</style>
<script>
$(function() {
$( "#resizable" ).resizable();
});
</script></head><body>
<div id="resizable" class="ui-widget-content">
<h3 class="ui-widget-header">缩放(Resizable)</h3></div>
</body></html>查看演示
动画
使用 animate 选项(布尔值)使缩放行为动画化。当该选项设置为 true 时,拖拽轮廓到所需的位置,元素会在拖拽停止时以动画形式调整到该尺寸。
<!doctype html><html lang="en"><head>
<meta charset="utf-8">
<title>jQuery UI 缩放(Resizable) - 动画</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://jqueryui.com/resources/demos/style.css">
<style>
#resizable { width: 150px; height: 150px; padding: 0.5em; }
#resizable h3 { text-align: center; margin: 0; }
.ui-resizable-helper { border: 1px dotted gray; }
</style>
<script>
$(function() {
$( "#resizable" ).resizable({
animate: true
});
});
</script></head><body>
<div id="resizable" class="ui-widget-content">
<h3 class="ui-widget-header">动画</h3></div>
</body></html>查看演示
限制缩放区域
定义缩放区域的边界。使用 containment 选项来指定一个父级的 DOM 元素或一个 jQuery 选择器,比如 'document.'。
<!doctype html><html lang="en"><head>
<meta charset="utf-8">
<title>jQuery UI 缩放(Resizable) - 限制缩放区域</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://jqueryui.com/resources/demos/style.css">
<style>
#container { width: 300px; height: 300px; }
#container h3 { text-align: center; margin: 0; margin-bottom: 10px; }
#resizable { background-position: top left; width: 150px; height: 150px; }
#resizable, #container { padding: 0.5em; }
</style>
<script>
$(function() {
$( "#resizable" ).resizable({
containment: "#container"
});
});
</script></head><body>
<div id="container" class="ui-widget-content">
<h3 class="ui-widget-header">限制</h3>
<div id="resizable" class="ui-state-active">
<h3 class="ui-widget-header">缩放(Resizable)</h3>
</div></div>
</body></html>查看演示
延迟开始
通过 delay 选项设置延迟开始缩放的毫秒数。通过 distance 选项设置光标被按下且拖拽指定像素后才允许缩放。
<!doctype html><html lang="en"><head>
<meta charset="utf-8">
<title>jQuery UI 缩放(Resizable) - 延迟开始</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://jqueryui.com/resources/demos/style.css">
<style>
#resizable, #resizable2 { width: 150px; height: 150px; padding: 0.5em; }
#resizable h3, #resizable2 h3 { text-align: center; margin: 0; }
</style>
<script>
$(function() {
$( "#resizable" ).resizable({
delay: 1000
});
$( "#resizable2" ).resizable({
distance: 40
});
});
</script></head><body>
<h3 class="docs">时间延迟 (ms):</h3><div id="resizable" class="ui-widget-content">
<h3 class="ui-widget-header">时间</h3></div>
<h3 class="docs">距离延迟 (px):</h3><div id="resizable2" class="ui-widget-content">
<h3 class="ui-widget-header">距离</h3></div>
</body></html>查看演示
助手
通过设置 helper 选项为一个 CSS class,当缩放时只显示元素的轮廓。
<!doctype html><html lang="en"><head>
<meta charset="utf-8">
<title>jQuery UI 缩放(Resizable) - 助手</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://jqueryui.com/resources/demos/style.css">
<style>
#resizable { width: 150px; height: 150px; padding: 0.5em; }
#resizable h3 { text-align: center; margin: 0; }
.ui-resizable-helper { border: 2px dotted #00F; }
</style>
<script>
$(function() {
$( "#resizable" ).resizable({
helper: "ui-resizable-helper"
});
});
</script></head><body>
<div id="resizable" class="ui-widget-content">
<h3 class="ui-widget-header">助手</h3></div>
</body></html>查看演示
最大/最小尺寸
使用 maxHeight、maxWidth、minHeight 和 minWidth 选项限制 resizable 元素的最大或最小高度或宽度。
<!doctype html><html lang="en"><head>
<meta charset="utf-8">
<title>jQuery UI 缩放(Resizable) - 最大/最小尺寸</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://jqueryui.com/resources/demos/style.css">
<style>
#resizable { width: 200px; height: 150px; padding: 5px; }
#resizable h3 { text-align: center; margin: 0; }
</style>
<script>
$(function() {
$( "#resizable" ).resizable({
maxHeight: 250,
maxWidth: 350,
minHeight: 150,
minWidth: 200
});
});
</script></head><body>
<div id="resizable" class="ui-widget-content">
<h3 class="ui-widget-header">放大/缩小</h3></div>
</body></html>查看演示
保持纵横比
保持现有的纵横比或设置一个新的纵横比来限制缩放比例。设置 aspectRatio 选项为 true,且可选地传递一个新的比率(比如,4/3)。
<!doctype html><html lang="en"><head>
<meta charset="utf-8">
<title>jQuery UI 缩放(Resizable) - 保持纵横比</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://jqueryui.com/resources/demos/style.css">
<style>
#resizable { width: 160px; height: 90px; padding: 0.5em; }
#resizable h3 { text-align: center; margin: 0; }
</style>
<script>
$(function() {
$( "#resizable" ).resizable({
aspectRatio: 16 / 9
});
});
</script></head><body>
<div id="resizable" class="ui-widget-content">
<h3 class="ui-widget-header">保持纵横比</h3></div>
</body></html>查看演示
对齐到网格
对齐 resizable 元素到网格。通过 grid 选项设置网格单元的尺寸(以像素为单位的高度和宽度)。
<!doctype html><html lang="en"><head>
<meta charset="utf-8">
<title>jQuery UI 缩放(Resizable) - 对齐到网格</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://jqueryui.com/resources/demos/style.css">
<style>
#resizable { width: 150px; height: 150px; padding: 0.5em; }
#resizable h3 { text-align: center; margin: 0; }
</style>
<script>
$(function() {
$( "#resizable" ).resizable({
grid: 50
});
});
</script></head><body>
<div id="resizable" class="ui-widget-content">
<h3 class="ui-widget-header">网格</h3></div>
</body></html>同步缩放
通过点击并拖拽一个元素的边来同时调整多个元素的尺寸。给 alsoResize 选项传递一个共享的选择器。
<!doctype html><html lang="en"><head>
<meta charset="utf-8">
<title>jQuery UI 缩放(Resizable) - 同步缩放</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://jqueryui.com/resources/demos/style.css">
<style>
#resizable { background-position: top left; }
#resizable, #also { width: 150px; height: 120px; padding: 0.5em; }
#resizable h3, #also h3 { text-align: center; margin: 0; }
#also { margin-top: 1em; }
</style>
<script>
$(function() {
$( "#resizable" ).resizable({
alsoResize: "#also"
});
$( "#also" ).resizable();
});
</script></head><body>
<div id="resizable" class="ui-widget-header">
<h3 class="ui-state-active">缩放</h3></div>
<div id="also" class="ui-widget-content">
<h3 class="ui-widget-header">同步缩放</h3></div>
</body></html>查看演示
文本框
可缩放的文本框。
<!doctype html><html lang="en"><head>
<meta charset="utf-8">
<title>jQuery UI 缩放(Resizable) - 文本框</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://jqueryui.com/resources/demos/style.css">
<style>
.ui-resizable-se {
bottom: 17px;
}
</style>
<script>
$(function() {
$( "#resizable" ).resizable({
handles: "se"
});
});
</script></head><body>
<textarea id="resizable" rows="5" cols="20"></textarea>
</body></html>视觉反馈
通过设置 ghost 选项为 true,可在缩放期间显示一个半透明的元素,而不是显示一个实际的元素。
每当打开淘宝,天猫等pc端时,看到心仪的物品时,点击图片时,便呈现出放大的效果。有没有去理解分析它的原理?是不是感觉非常的神奇?当真正地去接触,其实非常好理解。下面一起来学习!
Jquery和CSS3轻松实现放大镜效果
<div class="magnify"> <div class="large"></div> <img class="small" src="0413pf3.jpg"/> </div>
small是原始图片,large是放大镜片
.magnify{
position: relative;
}
.magnify img{
width: 100%;
}
.large {
width: 175px;
height: 175px;
position: absolute;
border-radius: 100%;
box-shadow: 0 0 0 7px rgba(255, 255, 255, 0.85),
0 0 7px 7px rgba(0, 0, 0, 0.25),
inset 0 0 40px 2px rgba(0, 0, 0, 0.25);
background: url('0413pf3.jpg') no-repeat;
display: none;
}
$(document).ready(function(){
var native_width=0;
var native_height=0;
// 监听鼠标在magnify元素移动
$(".magnify").mousemove(function(e){
if(!native_width && !native_height){
// 获取原始图片的宽高
var image_object=new Image();
image_object.src=$(".small").attr("src");
native_width=image_object.width;
native_height=image_object.height;
}else{
var magnify_offset=$(this).offset();
var mx=e.pageX - magnify_offset.left;
var my=e.pageY - magnify_offset.top;
if(mx < $(this).width() && my < $(this).height() && mx > 0 && my > 0) {
$(".large").fadeIn(100);
} else {
$(".large").fadeOut(100);
}
if($(".large").is(":visible")) {
var rx=Math.round(mx/$(".small").width()*native_width - $(".large").width() / 2) * -1;
var ry=Math.round(my/$(".small").height()*native_height - $(".large").height() / 2) * -1;
var bgp=rx + "px " + ry + "px";
var px=mx - $(".large").width()/2;
var py=my - $(".large").height()/2;
$(".large").css({left: px, top: py, backgroundPosition: bgp});
}
}
})
})
是不是觉得很简单了,代码量不大,原理了就是鼠标移动时,获取鼠标在原始图片的位置,计算出放大镜片图片的`background-osition`值,实时去修改,这样就形成了放大镜的效果。
需要源码和演示地址的同学,点击下方“了解更多”!
更多资源敬请关注!
言
在做电商类应用时,难免会遇到商品主图实现放大镜效果的场景,现有的基于Vue的第三方包不多并且无法直接复用,今天,我来分享一种高稳定性的基于 Vue 的图片放大镜方法。
实现原理
放大镜的原理用一句话概括,就是根据小图上的鼠标位置去定位大图。
图1 原理图(以2倍放大为例)
相信原理图已经画的很明白了, 图中,左侧框是小图框,其蓝色区域为图片遮罩层(需放大区域),右侧框是整个大图目前所在区域,其蓝色区域是放大区域,设置超出隐藏,就实现了放大遮罩区域的效果。
显然,两块蓝色区域存在着某种对应关系,即遮罩的左上角位置(相对于小图,以下称 X 坐标)和放大区域(相对于大图)的左上角位置是成比例的,即放大倍数。计算出 X 坐标后,适当调整背景图的位置,使大图向反方向移动 scale 倍的 X 坐标即可。
X 坐标为(maskX,maskY),以计算 maskX 为例:
鼠标移动中会产生 e.clientX ,标识鼠标与浏览器左侧的距离,小图与浏览器左侧的距离是 left ,由于遮罩始终是一个以鼠标为中心的正方形,所以:
maskX=e.clientX - left - mask/2
同理,
maskY=e.clientY - top - mask/2
大图的对应样式设置为:
{
left: - maskX * scale + 'px';
top: - maskY * scale + 'px';
}
复制代码
效果演示
图2 长图展示
图3 宽图展示
图4 两倍放大效果图
图5 四倍放大效果图
核心代码
HTML
一般放大镜实现的是 1:1 等宽等高的正方形图片,这里兼容了其他比例的图片,设置图片为垂直居中对齐,包括小图,大图。如果小图不够充满整个小图框,余留下的空白部分也可以有放大效果,只不过放大结果依然是空白。 这样只需计算背景图的移动距离,不用过多的关注图片定位问题。
<template>
<div class="magnifier">
<!-- 小图 -->
<div class="small-box" @mouseover="handOver" @mousemove="handMove" @mouseout="handOut">
<img class="smallPic" :src="`${src}?x-oss-process=image/resize,l_836`" />
<div class="magnifier-zoom"
v-show="showMask"
:style="{
background: configs.maskColor,
height: configs.maskWidth + 'px',
width: configs.maskHeight + 'px',
opacity: configs.maskOpacity,
transform: transformMask
}"
></div>
</div>
<!-- 大图, 注意误差 -->
<div class="magnifier-layer"
v-show="showMagnifier"
:style="{
width: configs.width + 'px',
height: configs.height + 'px',
left: configs.width + 20 + 'px'
}"
>
<div class="big-box"
:style="{
width: bigWidth + 'px',
height: bigHeight + 'px',
left: moveLeft,
top: moveTop
}"
>
<div class="big-box-img"
:style="{
width: bigWidth - 2 + 'px',
height: bigHeight - 2 + 'px'
}"
>
<img
:src="bigSrc"
:style="{
maxWidth: bigWidth - 2 + 'px',
maxHeight: bigHeight -2 + 'px'
}"
/>
</div>
</div>
</div>
</div>
</template>
复制代码
JS
这里主要有三个事件函数。
handOver() {
// 计算小图框在浏览器中的位置
this.imgObj=this.$el.getElementsByClassName('small-box')[0];
this.imgRectNow=this.imgObj.getBoundingClientRect();
this.showMagnifier=true;
this.showMask=true;
}
复制代码
handMove(e) {
// 计算初始的遮罩左上角的坐标
let objX=e.clientX - this.imgRectNow.left;
let objY=e.clientY - this.imgRectNow.top;
// 计算初始的遮罩左上角的坐标
let maskX=objX - this.configs.maskWidth / 2;
let maskY=objY - this.configs.maskHeight / 2;
// 判断是否超出界限,并纠正
maskY=maskY < 0 ? 0 : maskY;
maskX=maskX < 0 ? 0 : maskX;
if(maskY + this.configs.maskHeight >=this.imgRectNow.height) {
maskY=this.imgRectNow.height - this.configs.maskHeight;
}
if(maskX + this.configs.maskWidth >=this.imgRectNow.width) {
maskX=this.imgRectNow.width - this.configs.maskWidth;
}
// 遮罩移动
this.transformMask=`translate(${maskX}px, ${maskY}px)`;
// 背景图移动
this.moveLeft=- maskX * this.configs.scale + "px";
this.moveTop=- maskY * this.configs.scale + "px";
}
复制代码
handOut() {
this.showMagnifier=false;
this.showMask=false;
}
复制代码
以上三个事件基本上就实现了图片的放大镜功能。
但仔细看,你会发现每次移入小图框都会触发一次 handOver 事件,并且计算一次小图框 DOM (imgObj) 。
为了优化此问题,可以用 init 标识是否是页面加载后首次触发 handOver 事件,如果是初始化就计算imgObj 信息,否则不计算。
handOver() {
if (!this.init) {
this.init=true;
// 原 handOver 事件
...
}
this.showMagnifier=true;
this.showMask=true;
},
复制代码
在测试的过程中,发现页面滚动后,会出现遮罩定位错误的情况,原来是因为初始化时,我们固定死了小图框的位置信息(存放在 this.imgRectNow ),导致 handMove 事件中的移动数据计算错误。
解决这个问题有两种方案:
这里选择了第二种。
handMove(e) {
// 动态获取小图的位置(或者监听 scroll )
let imgRectNow=this.imgObj.getBoundingClientRect();
let objX=e.clientX - imgRectNow.left;
let objY=e.clientY - imgRectNow.top;
// 原 handMove 事件剩余内容
...
},
复制代码
综合以上,我们已经实现了一个完美的图片放大镜功能。最终的 js 如下所示:
data() {
return {
imgObj: {},
moveLeft: 0,
moveTop: 0,
transformMask:`translate(0px, 0px)`,
showMagnifier:false,
showMask:false,
init: false,
};
},
computed: {
bigWidth(){
return this.configs.scale * this.configs.width;
},
bigHeight(){
return this.configs.scale * this.configs.height;
}
},
methods: {
handMove(e) {
// 动态获取小图的位置(或者监听 scroll )
let imgRectNow=this.imgObj.getBoundingClientRect();
let objX=e.clientX - imgRectNow.left;
let objY=e.clientY - imgRectNow.top;
// 计算初始的遮罩左上角的坐标
let maskX=objX - this.configs.maskWidth / 2;
let maskY=objY - this.configs.maskHeight / 2;
// 判断是否超出界限,并纠正
maskY=maskY < 0 ? 0 : maskY;
maskX=maskX < 0 ? 0 : maskX;
if(maskY + this.configs.maskHeight >=imgRectNow.height) {
maskY=imgRectNow.height - this.configs.maskHeight;
}
if(maskX + this.configs.maskWidth >=imgRectNow.width) {
maskX=imgRectNow.width - this.configs.maskWidth;
}
// 遮罩移动
this.transformMask=`translate(${maskX}px, ${maskY}px)`;
// 背景图移动
this.moveLeft=- maskX * this.configs.scale + "px";
this.moveTop=- maskY * this.configs.scale + "px";
},
handOut() {
this.showMagnifier=false;
this.showMask=false;
},
handOver() {
if (!this.init) {
this.init=true;
this.imgObj=this.$el.getElementsByClassName('small-box')[0];
}
this.showMagnifier=true;
this.showMask=true;
}
}
复制代码
使用方法
本示例中的固定参数:小图框:420 * 420 。
程序可接受参数:
// 小图地址
src: {
type: String,
},
// 大图地址
bigSrc: {
type: String,
},
// 配置项
configs: {
type: Object,
default() {
return {
width:420,//放大区域
height:420,//放大区域
maskWidth:210,//遮罩
maskHeight:210,//遮罩
maskColor:'rgba(25,122,255,0.5)',//遮罩样式
maskOpacity:0.6,
scale:2,//放大比例
};
}
}
复制代码
文中图 2 是一张长图,小图的最大边不超过 836px(二倍图) ,大图为了视觉效果,分辨率尽量高点,程序会根据配置项自动设置对应的 height , width ,长图与宽图的效果对比可参考图3。
配置项可根据应用场景自行设置,本文示例的配置项是 2 倍放大,效果可参考图 4,四倍放大效果可参考图 5。
总结
其实图片放大镜的实现思路没有那么复杂,核心点有两点:
本文顺着这个思路,做了一个简单的实现,还有一些优化的空间,欢迎各位大佬在评论区讨论。虽然代码看起来不是非常优雅,但是足够明了,感兴趣的同学可以自己尝试一下。
*请认真填写需求信息,我们会在24小时内与您取得联系。