# 拖拽的实现
主要用到offsetX,offsetY,pageX,pageY,document.documentElement.clientWidth,document.documentElement.clientHeight
~~~
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<script src="main.js"></script>
<style>
html,
body {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
}
#father {
position: relative;
height: 100%;
width: 100%;
}
#son {
height: 100px;
width: 100px;
background-color: green;
position: absolute;
}
</style>
</head>
<body>
<div id="father">
<div id="son"></div>
</div>
</body>
<script>
(function () {
var father = document.getElementById('father')
var son = document.getElementById('son')
var dragging = false;
var positionSonX, positionSonY, mouseX, mouseY, offsetX, offsetY;
son.onmousedown = down;
document.onmousemove = move;
document.onmouseup = leave;
function down(e) {
dragging = true;
positionSonX = son.offsetLeft; // son相对于father的left
positionSonY = son.offsetTop; // son相对于father的top
mouseX = parseInt(getMouseXY(e).x); // 获取鼠标当前的位置X坐标
mouseY = parseInt(getMouseXY(e).y); // 获取鼠标当前的位置Y坐标
offsetX = mouseX - positionSonX; // 计算得到偏移量
offsetY = mouseY - positionSonY; // 计算得到偏移量
}
function move(e) {
if (dragging) {
var x = getMouseXY(e).x - offsetX;
var y = getMouseXY(e).y - offsetY;
var width = document.documentElement.clientWidth - son.offsetWidth;
var height = document.documentElement.clientHeight - son.offsetHeight;
x = Math.min(Math.max(0, x), width);
y = Math.min(Math.max(0, y), height);
son.style.left = x + 'px';
son.style.top = y + 'px';
}
}
function leave() {
dragging = false;
}
function getMouseXY(e) {
var x = 0, y = 0;
e = e || window.event;
if (e.pageX) {
x = e.pageX;
y = e.pageY;
}
return {
x, y
}
}
})()
</script>
</html>
~~~
- html
- 冒泡/捕获/委托
- 前端路由
- Dom
- 创建节点API
- 页面修改型API
- 节点查询型API
- 节点关系型API
- 元素属性API
- DOM事件
- classList
- 性能优化
- 节流防抖
- localStorage sessionStorage
- BOM
- meta
- data属性
- js实现拖拽
- html5
- 关于meta
- 轮播图
- js实现拖放
- 电话号inputFormater
- js
- es6
- promise
- iterator
- generator
- async
- proxy
- Set
- Map
- Object的扩展
- String
- Iterator
- Symbol
- 解构赋值
- 函数式编程
- module
- 基本数据类型
- 数组相关codings
- for of/for in
- this
- call bind apply
- 闭包
- 作用域
- prototype与继承
- 深浅拷贝
- setTimeOut/setInterval
- 垃圾处理机制
- 设计模式
- 观察者模式
- 单例模式
- 策略模式
- RegExp
- with
- 其他玩意
- Error/Stack Trace
- 面向对象
- css
- 回流重绘
- %取值
- 属性继承/属性优先级
- flex
- BFC
- 盒模型
- 设置css的方法
- 定位机制
- 块级/行内元素
- hack和一些别的玩意
- css动画
- 几个布局
- 画图形
- css3
- animation对比transform
- 点击不同图片区域跳转不同
- css选择器性能问题
- vh rem em
- css选择器
- 伪类伪元素
- css匹配原理
- 数据结构与算法
- 数据结构
- 树
- 链表
- 栈和队列
- 排序
- 归并排序
- 插入排序
- 选择排序
- 冒泡排序
- 快速排序
- 递归
- 回溯法
- 搜索算法
- 动态规划
- http
- 跨域问题
- CORS
- GET/POST
- ajax
- ajax上传文件
- http缓存
- https
- TCP/UDP
- cookie/session
- http2.0
- spdy
- websocket
- React
- redux
- 生命周期
- 虚拟dom与diff
- 双向数据绑定
- mvvm
- setState
- contextApi props reudx
- 高阶组件
- react-redux
- Fiber
- react-router
- 受控/非受控组件
- 待整理
- webpack
- loader实现
- 前端安全
- 移动端适配
- Vue
- 传值
- 其他