案例
点击效果
<style>
*{
margin: 0;
padding:0;
}
body{
height: 50000px;
}
div{
width: 100px;
height: 100px;
background: pink;
position: fixed;
top:0px;
left:0px;
}
</style>
</head>
<body>
<div></div>
<script>
// 点击鼠标,让div出现在,鼠标点击的位置上
// 实现方式:
// 点击时,获取鼠标点击位置的坐标,是针对视窗窗口的坐标
// 将这个数值,作为标签定位的数据
var oDiv = document.querySelector('div');
// 如果没有,padding和border,只要获取宽度就可以
// 有px单位,parseInt() 只获取数值,不要px
// 实际项目中,还需要定义兼容性
// var oDivHeight1 = parseInt(window.getComputedStyle(oDiv).height) ;
// 如果要有是有,padding和border,需要使用 offsetHeight 来获取
// 只有数值,没有px单位
// 推荐使用
var oDivHeight2 = oDiv.offsetHeight;
// console.log(oDivHeight1 , oDivHeight2);
var oDivWidth = oDiv.offsetWidth;
window.onclick = function(e){
// console.log(e);
// 这个数值只有 数, 没有px单位
// 作为定位的属性值,需要拼接px单位
// 让标签的左上角和鼠标点击的位置重合
// oDiv.style.left = e.clientX + 'px' ;
// oDiv.style.top = e.clientY + 'px' ;
// 让标签的左上角 和 鼠标点击位置 有间距
// 在原始数值的基础上,再多加上一定的数值
// 这个数值,是根据客户需求而定,现在随便加个数,意思意思
// oDiv.style.left = e.clientX + 20 + 'px' ;
// oDiv.style.top = e.clientY + 20 + 'px' ;
// 让标签的中心 和 鼠标点击位置 重合
// 在原始数值的基础上,再减去定位标签,宽高的一半
oDiv.style.left = e.clientX - oDiv.offsetWidth/2 + 'px' ;
oDiv.style.top = e.clientY - oDiv.offsetHeight/2 + 'px' ;
}
</script>
拖拽效果
<style>
*{
margin: 0;
padding:0;
}
body{
height: 5000px;
}
div{
width: 100px;
height: 100px;
background: pink;
position: fixed;
top:200px;
left:200px;
}
</style>
</head>
<body>
<div></div>
<script>
// 拖拽的效果
// 当鼠标按下时
// 并且鼠标移动时
var oDiv = document.querySelector('div');
// 在div移动之前,先记录原始的定位数据
var oldTop = window.getComputedStyle(oDiv).top;
var oldLeft = window.getComputedStyle(oDiv).left;
// 当鼠标按下时,鼠标移动,添加事件
window.onmousedown = function(){
window.onmousemove = function(e){
// 将鼠标的坐标,作为div定位的数值,定位的是中心的位置
oDiv.style.left = e.clientX - oDiv.offsetWidth/2 + 'px' ;
oDiv.style.top = e.clientY - oDiv.offsetHeight/2 + 'px' ;
}
}
// 当鼠标抬起时,鼠标移动,赋值null,就没有事件执行了
window.onmouseup = function(){
window.onmousemove = null;
// 可以再给div定义,定位位置,可以返回原始位置
// 也在函数之外,记录存储原始位置
oDiv.style.left = oldLeft;
oDiv.style.top = oldTop;
}
// 如果想要鼠标移动的快点 把 oDiv 改变成 window 或者 document
// 先 鼠标移动,里面定义鼠标按下,抬起
// 鼠标移动时,执行鼠标按下,鼠标按下,计算机只会触发一次
// 鼠标按下,即时是一直按,只会触发一次
// 定义的程序,只会回执一次
// window.onmousemove = function(){
// window.onmousedown = function(){
// console.log(123);
// }
// }
// 按下的时候,执行鼠标移动
// 鼠标移动会一直触发,移动中定义的程序,会一直执行
// window.onmousedown = function(){
// window.onmousemove = function(){
// console.log(456);
// }
// }
</script>
</body>
拖拽边界
第一
<style>
*{
margin: 0;
padding:0;
}
body{
height: 5000px;
}
div{
width: 100px;
height: 100px;
padding: 100px;
background: pink;
border:10px solid black;
position: fixed;
top:0px;
left:0px;
}
</style>
<body>
<div></div>
<script>
// 拖拽的效果 --- 边界值
// 鼠标移动出页面,但是div要留在页面范围内
// 给定位数值,添加极限范围数值,
// 定位的最大值,最小值,都要有范围
// 最小值 : 上 左 都是 0
//
var oDiv = document.querySelector('div');
var oldTop = window.getComputedStyle(oDiv).top;
var oldLeft = window.getComputedStyle(oDiv).left;
// 视窗窗口的宽度,高度
var winWidth = document.documentElement.clientWidth;
var winHeight = document.documentElement.clientHeight;
// 当鼠标按下时,鼠标移动,添加事件
window.onmousedown = function(){
window.onmousemove = function(e){
// 根据 鼠标坐标,根据项目需求,计算定位的数值
var x = e.clientX - oDiv.offsetWidth/2;
var y = e.clientY - oDiv.offsetHeight/2;
// 极限值判断
// 最小值都是 0 0
if(x < 0){
x = 0;
}
if(y < 0){
y = 0;
}
// 最大值 可视窗口的宽度/高度 - ( 标签x轴方向 / y轴方向 最终占位 )
if(x > winWidth - oDiv.offsetWidth){
x = winWidth - oDiv.offsetWidth;
}
if(y > winHeight - oDiv.offsetHeight){
y = winHeight - oDiv.offsetHeight;
}
console.log(x,y);
// 将数值作为标签定位的坐标
oDiv.style.left = x + 'px' ;
oDiv.style.top = y + 'px' ;
}
}
window.onmouseup = function(){
window.onmousemove = null;
}
// 总结思路
// 1,一定是 先按下事件,后移动事件 --- 先砍头再移尸
// 2,鼠标抬起,给移动定义事件为null
// 也可以添加其他操作,例如,让标签回到原位
// 回到原始位置,需要在程序的起始位置,先记录原始的定位坐标
// 3,基本思路
// (1),在定义函数之外,获取浏览器窗口的宽度,高度
// 不能带有滚动条
// (2),获取鼠标的坐标,根据项目需求,来计算表现定位的数值
// 鼠标的坐标,要根据实际需求而定,目前使用的是相对可视窗口左上角的定位
// 项目需求不同,+ / - 的数值也不同
// (3),设定极值
// 最小值为 0 0
// 最大值为 可视窗口宽度/高度 - 标签X轴/Y轴最终占位
// (4),将最终的数据,作为标签定位的坐标
// 必须拼接px单位
</script>
第二
</body>
<style>
* {
padding: 0;
margin: 0;
}
body {
height: 5000px;
}
.box {
width: 800px;
height: 800px;
border: 10px solid #000;
margin: 40px auto;
position: relative;
background: skyblue;
}
.inner {
width: 100px;
height: 100px;
background: pink;
position: absolute;
top: 0;
left: 0;
}
</style>
</head>
<body>
<div class="box">
<div class="inner"></div>
</div>
<script>
// 1,获取标签对象
var oBox = document.querySelector('.box');
var oInner = document.querySelector('.inner');
// 2,获取相应的数据
// 获取父级标签的---占位---不包括边框线
var oBoxWidth = oBox.clientWidth;
var oBoxHeight = oBox.clientHeight;
// 获取子级标签的---占位---包括边框线
var oInnerWidth = oInner.offsetWidth;
var oInnerHeight = oInner.offsetHeight;
// 给父级标签添加事件
oInner.onmousedown = function () {
document.onmousemove = function (e) {
// 获取计算,设定子级标签定位的数值
// page坐标 - 外边距 - 边框线 - 子级宽度的一半
var x = e.pageX - oBox.offsetLeft - oBox.clientLeft - oInnerWidth / 2;
var y = e.pageY - oBox.offsetTop - oBox.clientTop - oInnerHeight / 2;
// 设定极限值
// 最小值是0
if (x < 0) {
x = 0;
}
if (y < 0) {
y = 0;
}
// 最大值
// 父级标签占位(没有border) - 移动标签占位(计算border)
if (x > oBoxWidth - oInnerWidth) {
x = oBoxWidth - oInnerWidth;
}
if (y > oBoxHeight - oInnerHeight) {
y = oBoxHeight - oInnerHeight
}
// 将设定好的数值,作为子级标签的定位
oInner.style.left = x + 'px';
oInner.style.top = y + 'px';
}
}
window.onmouseup = function () {
document.onmousemove = null;
}
// 思路步骤和问题
// 1, 事件,到底是绑定给 父级,子级,还是document,还是window
// 事件,取消,到底是通过谁取消
// 没有固定的写法,看你需要的效果
// 还是document和window效果相同,没有区别
// 鼠标按下
// oInner.onmousedown 鼠标在粉色div上,按下鼠标,并且移动鼠标,才会有效果
// oBox.onmousedown 鼠标在蓝色div上,按下鼠标,并且移动鼠标,才会有效果
// window.onmousedown 鼠标在全屏上,按下鼠标,并且移动鼠标,都会有效果
// 鼠标移动
// 最好写成 document.onmousemove / window.onmousemove
// 鼠标可以快速移动,不怕移出粉色div
// 鼠标抬起
// oInner.onmouseup 鼠标在粉色div上抬起,才会执行,标签不跟随移动
// oBox.onmouseup 鼠标在蓝色div上抬起,才会执行,标签不跟随移动
// window.onmouseup 鼠标在整个页面上抬起,都会执行,标签不跟随移动
// 2, 闪烁问题
// 原因: 相对于标签内容的左上角的定位
// 会因为鼠标经过不同的标签对象,获取不同的数据
// 而且JavaScript执行时,有时还会有bug产生
// offsetX offsetY 我们是不推荐使用的
// 解决: 使用 pageX 和 pageY
// 定位: page距离 - 父级标签外边距 - 父级border - 移动标签占位/2(标签中心点和鼠标重合)
// 极值1: 左 上 都是 0
// 极值2: 右 下 父级标签占位(不算border) - 移动标签占位(计算border)
</script>
tab切换-选项卡
<style>
*{
margin: 0;
padding:0;
}
ul,ol,li{
list-style: none;
}
.cont{
width: 800px;
height: 600px;
border: 5px solid #333;
margin: 0 auto;
display: flex;
flex-direction: column;
}
.cont ul{
width: 100%;
height: 60px;
display: flex;
}
.cont ul li{
flex:1;
font-size: 35px;
color: #fff;
border-left: 2px solid blue;
border-right: 2px solid blue;
background: hotpink;
display: flex;
justify-content: center;
align-items: center;
}
.cont ol{
flex:1;
position: relative;
}
.cont ol li{
width: 100%;
height: 100%;
font-size: 150px;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top:0;
left:0;
background: burlywood;
display: none;
}
/* 按钮标签 哪个标签有这个属性,哪个就显示特殊背景颜色 */
.cont ul li.active{
background: skyblue;
color: black;
}
/* 内容标签 哪个标签有这个属性,哪个就显示 */
.cont ol li.active{
display: flex;
}
</style>
</head>
<body>
<div class="cont">
<ul>
<li class="active">按钮1</li>
<li>按钮2</li>
<li>按钮3</li>
</ul>
<ol>
<li class="active">内容1</li>
<li >内容2</li>
<li>内容3</li>
</ol>
</div>
<script>
// tab切换 / 选项卡 效果
// 实现思路:
// 1, ul中的li标签个数 和 ol中li标签个数是相同的
// 按钮和内容是一一对应的
// 2, 点击按钮标签,也就是ul中的li标签
// 给当前这个li标签,添加class样式,给其他的li标签,去除class样式
// 实现思路: 先给所有的li标签,去除class样式
// 再给当前的li标签,添加class样式
// 3, 点击按钮标签,也就是ul中的li标签
// 给 ol 中所有的 li标签,去除class样式
// 给 与 当前 ul>li 索引相同的 ol>li标签,添加样式
var oUllis = document.querySelectorAll('ul li');
var oOllis = document.querySelectorAll('ol li');
// 循环 ul中的所有li,添加点击事件
oUllis.forEach(function(item , key){
// ul中的li标签 , item就是ul中的li标签
item.onclick = function(){
// 1,清除所有的ul,ol,中li的class样式属性
// 循环遍历所有的ul和ol中的标签
oUllis.forEach(function(v , k){
// v是ul中的li标签
v.className = '';
// ul>li和ol>li索引是相同的
// 通过ul中li的索引也可以获取ol中的li标签
// oOllis[k] 就是 ol中的li标签
oOllis[k].className = '';
})
// 循环结束,所有的ul,ol中,li都没有active
// 给当前点击的item标签,也就是ul,li标签,添加样式
item.className = 'active';
// 给ol中,对应的这个标签的索引的li标签,添加样式
oOllis[key].className = 'active';
}
})
// 不想用forEach,也可以试试事件委托
// 总结
// 核心思路:
// 利用 ul 和 ol 中 li标签个数相同的 特点,优化程序,简化代码
// 1,获取标签对象
// 2,给所有的ul中的li标签,添加点击事件
// 3,点击事件执行的内容
// (1),给所有的ul和ol中的li标签,清除样式
// (2),给当前点击的ul中的li标签,添加样式
// (3),给索引相同的ol中的li标签,添加样式
// 可以用自己的方式实现,比如多写几个循环,分别操作ul和ol中的标签
// 不过我的方法比较简单
// 也可以尝试事件委托的方式,给div标签,添加点击事件
// 判断点击的li标签,定义程序
// 不过这样的话,要给ul中li标签,添加不少的设定,以区别ul>li和ol>li
</script>