2013年10月

移动端开发实例 | 圖片滑動 | 模擬滾動條

圖片滑動
onmousedown -->> ontouchstart按下瞬间 ;
onmousemove -->> ontouchmove移动过程 ;
onmouseup -->> ontouchend手指抬起 ,只针对单手操作 ;
對象操作:

var touchs = e.changedTouches[0]  
//先获取对象属性,手指操作的集合; 几个手指即有几项,所以单指是[0] ;

所以與元素拖動類似,結構是:

_ul.ontouchstart = function(e){
    _ul.ontouchmove  = function(e){
        ...
    }
    _ul.ontouchend  = function(e){
        ...
         this.ontouchmove = this.ontouchend = null;
    }
}

第一張圖與最後一張圖時速度變慢,所以使用移動距離為1/3

this.style.left = (touchs.pageX - downX) / 3 + 'px'

若第一張與第二張中間切換時,速度不同會出現跳動,所以需要再move過界時重新獲取downX,並且設置開頭只獲取一次;

   b = false
   downX = touchs.pageX

如果快速移動時,可快速滑動,需要設置時間,start時的時間,到end的時間

downTime = Date.now(); 

    _ul.ontouchend = function(e){
    ...
    Date.now() - downTime < 300  
    }
<div id="div">
    <ul id="ul1">
        <li><img src="iosimg/1.jpg" alt=""/></li>
        <li><img src="iosimg/2.jpg" alt=""/></li>
        <li><img src="iosimg/3.jpg" alt=""/></li>
        <li><img src="iosimg/4.jpg" alt=""/></li>
        <li><img src="iosimg/5.jpg" alt=""/></li>
    </ul>
</div>
var _div = document.getElementById('div')
var _ul = document.getElementById('ul1')
var _li = _ul.getElementsByTagName('li')
var w = _li[0].offsetWidth;
_ul.style.width = w * _li.length + 'px'
document.ontouchmove = function (e) {  //阻止默認滑動
    e.preventDefault()
}

var downX = 0;   //手指點下的坐標
var downLeft = 0;
var downTime = 0;
var inow = 0;
_ul.ontouchstart = function (e) {
    var touchs = e.changedTouches[0]  //先获取对象属性,手指操作的集合; 几个手指即有几项,所以单指是[0]

    downX = touchs.pageX
    downLeft = this.offsetLeft;
    var b = true;
    downTime = Date.now();

    _ul.ontouchmove = function (e) {
        var touchs = e.changedTouches[0]
        if (this.offsetLeft >= 0) {
            if (b) { //第二张一点开始滑到,到第一张时,如果不重新获取downX值,第二张速度仅为1/3,所以会突然跳动,设开头的意思是在move移动中,只需获取一次,不然只要move则每一秒都会重新获取;
                b = false
                downX = touchs.pageX
            }
            this.style.left = (touchs.pageX - downX) / 3 + 'px'

        }
        else if (this.offsetLeft < _div.offsetWidth - _ul.offsetWidth) {
            if (b) { //第二张一点开始滑到,到第一张时,如果不重新获取downX值,第二张速度仅为1/3,所以会突然跳动,设开头的意思是在move移动中,只需获取一次,不然只要move则每一秒都会重新获取;
                b = false
                downX = touchs.pageX
            }
            this.style.left = (touchs.pageX - downX) / 3 + (_div.offsetWidth - _ul.offsetWidth) + 'px'

        }
        else {
            this.style.left = touchs.pageX - downX + downLeft + 'px'
        }
    }
    _ul.ontouchend = function (e) {
        var touchs = e.changedTouches[0]
        if (touchs.pageX < downX) { //向左
            if (inow != _li.length - 1) {
                if (downX - touchs.pageX > w / 2 || Date.now() - downTime < 300 && downX - touchs.pageX > 30) {  //必须过一半才滑动
                    inow++ //确定方向,快速滑动,防止点击
                }
            }
            tMove(this, {left: -w * inow}, 500, 'easeOut')

        }
        else { //向右
            if (inow != 0) {
                if (touchs.pageX - downX > w / 2 || Date.now() - downTime < 300 && touchs.pageX - downX > 30) {
                    inow--
                }
            }
            tMove(this, {left: -w * inow}, 500, 'easeOut')
        }
        this.ontouchmove = this.ontouchend = null;
    }
}
    *{ margin: 0; padding: 0;}
    #div{ width: 470px; height: 150px; margin: 50px; position: relative;overflow: hidden; }
    #ul1{ position: absolute; left: 0; } /*这种而已没有宽度则li不会有float效果;*/
    #ul1 li{ width: 470px; height: 150px; float: left;list-style:none;}

模擬滾動條:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title><meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"/>
    <meta name="format-detection" content="telephone=no"/>
    <meta name="format-detection" content="email=no"/>
</head>
<body>
<style>
    *{ margin: 0; padding: 0;}
    #div1{ width: 200px; height: 200px;border:1px solid #000; position: relative; margin:100px;}
    #ul1{ position: absolute; top: 0;width: 100%;}
    #bar{ width: 2px; height: 100px; position: absolute; top: 0;right: 2px; background: #999; border-radius: 20px; display: none;}/* divH/ulH = barH/divH borH = divH*divH/ulH */
</style>
<div id="div1">
    <ul id="ul1">
    </ul>
    <div id="bar"></div>
</div>
</body>
<script>
    document.ontouchmove = function (e) {
        e.preventDefault()
    }
    var _div = document.getElementById('div1')
    var _ul = document.getElementById('ul1')
    var _bar = document.getElementById('bar')
    for(var i=0;i<101;i++){
        var _li = document.createElement('li')
        _li.innerHTML = i;
        _ul.appendChild(_li)
    }
    var downY = 0;
    var downTop = 0;
    var prevY = 0;

    var _t = null;

    var barH = _div.offsetHeight*_div.offsetHeight/_ul.offsetHeight
    if(barH<=40){
        barH = 40;
    }
    else if(_ul.offsetHeight<_div.offsetHeight){
        barH = 0;
    }
    _bar.style.height =barH + 'px'
    
    _ul.ontouchstart = function (e) {
        var touchs = e.changedTouches[0]

        downY = touchs.pageY
        downTop = this.offsetTop;
        prevY = touchs.pageY;

        var _speedY = 0;
        var b = true;

        _ul.ontouchmove= function (e) {

            _bar.style.opacity = 1;
            _bar.style.display = 'block';

          var touchs = e.changedTouches[0]
            _speedY = touchs.pageY - prevY; //出手速度 move时的点 - 前一个点,
            prevY = touchs.pageY;  //注意永运是最后一个点 - 前一个点,所以给值后要把prevY还原回前一个点;注意理解;
            if(this.offsetTop>=0){ //头部
                if(b){
                    b = false;
                    downY = touchs.pageY
                }
                this.style.top = (touchs.pageY - downY)/3 + downTop + 'px'
                _bar.style.height = barH * (1- this.offsetTop/_div.offsetHeight) +'px'//原高度 * 比例
                _bar.style.top = 0
            }
            else if(this.offsetTop<=_div.offsetHeight - _ul.offsetHeight){
                if(b){
                    b = false;
                    downY = touchs.pageY
                }
                this.style.top = (touchs.pageY - downY)/3 + _div.offsetHeight - _ul.offsetHeight + 'px'
                _bar.style.height = barH * (1- Math.abs((this.offsetTop-(_div.offsetHeight - _ul.offsetHeight))/_div.offsetHeight)) +'px'//原高度 * 比例  //尾部找一个0-1越来越小的值
                _bar.style.top = _div.offsetHeight - _bar.offsetHeight + 'px'
            }
            else{this.style.top = touchs.pageY - downY + downTop + 'px';

            //在move时找bar的滚动位置比例
                var scaleY = this.offsetTop/(_div.offsetHeight - _ul.offsetHeight) //最小值即move时不断变化的this.offsetTop,最大值为div.offsetHeight - _ul.offsetHeight; 0-1的比值
                _bar.style.top = scaleY * (_div.offsetHeight - _bar.offsetHeight)+'px'
            }
        }
        _ul.ontouchend = function () {
            this.ontouchmove = this.ontouchend = null;
            //1/手指起时开始做运动
            //_speedY
            var _this = this
            clearInterval(_t)
            _t = setInterval(function () {
                if(Math.abs(_speedY)<=1 || _this.offsetTop>50 || _this.offsetTop<=_div.offsetHeight - _ul.offsetHeight - 50){  //停
                    clearInterval(_t)
                    if(_this.offsetTop>=0){ //限制头
                        tMove(_this,{top:0},400, function () {
                            tMove(_bar,{opacity:0},400, function () {
                                this.style.display = 'none'
                            })

                        })
                        tMove(_bar,{height:barH},400)
                    }
                    else if(_this.offsetTop <= _div.offsetHeight - _ul.offsetHeight  ){ //限制尾
                        tMove(_this,{top:_div.offsetHeight - _ul.offsetHeight },400, function () {
                            tMove(_bar,{opacity:0},400, function () {
                                this.style.display = 'none'
                            })

                        })
                        tMove(_bar,{height:barH,top:_div.offsetHeight - barH},400, function () {
                            tMove(_bar,{opacity:0},400)
                            _bar.style.display = 'none'
                        })
                    }
                    else{  tMove(_bar,{opacity:0},400, function () {
                        this.style.display = 'none'
                    })

                    }
                }
                else{  //走
                    _speedY *=0.95;
                    _this.style.top = _this.offsetTop+ _speedY + 'px'

                    //bar头尾加运动

                    if(_this.offsetTop>=0){
                        _bar.style.height = barH * (1- _this.offsetTop/_div.offsetHeight) +'px'//原高度 * 比例
                        _bar.style.top = 0
                    }
                    else if(_this.offsetTop<=_div.offsetHeight - _ul.offsetHeight){
                        _bar.style.height = barH * (1- Math.abs((_this.offsetTop-(_div.offsetHeight - _ul.offsetHeight))/_div.offsetHeight)) +'px'//原高度 * 比例  //尾部找一个0-1越来越小的值
                        _bar.style.top = _div.offsetHeight - _bar.offsetHeight + 'px'
                    }
                    else{}
                    //在move时找bar的滚动位置比例
                    var scaleY = _this.offsetTop/(_div.offsetHeight - _ul.offsetHeight) //最小值即move时不断变化的this.offsetTop,最大值为div.offsetHeight - _ul.offsetHeight; 0-1的比值
                    _bar.style.top = scaleY * (_div.offsetHeight - _bar.offsetHeight)+'px'
                    tMove(_bar,{top:scaleY * (_div.offsetHeight - _bar.offsetHeight)},400)
                }
            },30)
        }
    }

    function tMove(obj, json, times, fx, fn) {
        if (typeof times == 'undefined') {
            times = 400;
            fx = 'linear';
        }
        if (typeof times == 'string') {
            if (typeof fx == 'function') {
                fn = fx;
            }
            fx = times;
            times = 400;
        }
        else if (typeof times == 'function') {
            fn = times;
            times = 400;
            fx = 'linear';
        }
        else if (typeof times == 'number') {
            if (typeof fx == 'function') {
                fn = fx;
                fx = 'linear';
            }
            else if (typeof fx == 'undefined') {
                fx = 'linear';
            }
        }
        var iCur = {
        }; //不變,不能寫在定時器裏  b
        for (var attr in json) {
            iCur[attr] = 0;
            if (attr == 'opacity') {
                iCur[attr] = Math.round(css(obj, attr) * 100);
            }
            else {
                iCur[attr] = parseInt(css(obj, attr));
            }
        }
        var startTime = now();
        clearInterval(obj._t);
        obj._t = setInterval(function () {
            var changeTime = now();
            var t = times - Math.max(0, startTime - changeTime + times);
            //在time的範圍內越來越小  2000-0;
            for (var attr in json) {
                var value = Tween[fx](t, iCur[attr], json[attr] - iCur[attr], times); //目的,通過js獲取tbcd值
                if (attr == 'opacity') {
                    obj.style.opacity = value / 100;
                    obj.style.filter = 'alpha(opacity=' + value + ')';
                }
                else {
                    obj.style[attr] = value + 'px';
                }
            }
            if (t == times) {
                clearInterval(obj._t);
                fn && fn.call(obj);
            }
        }, 13)
    }
    function now() {
        return (new Date()).getTime();
    }
    var Tween = {
        linear: function (t, b, c, d) { //匀速
            return c * t / d + b;
        },
        easeIn: function (t, b, c, d) { //加速曲线
            return c * (t /= d) * t + b;
        },
        easeOut: function (t, b, c, d) { //减速曲线
            return - c * (t /= d) * (t - 2) + b;
        },
        easeBoth: function (t, b, c, d) { //加速减速曲线 缓冲
            if ((t /= d / 2) < 1) {
                return c / 2 * t * t + b;
            }
            return - c / 2 * ((--t) * (t - 2) - 1) + b;
        },
        easeInStrong: function (t, b, c, d) { //加加速曲线
            return c * (t /= d) * t * t * t + b;
        },
        easeOutStrong: function (t, b, c, d) { //减减速曲线
            return - c * ((t = t / d - 1) * t * t * t - 1) + b;
        },
        easeBothStrong: function (t, b, c, d) { //加加速减减速曲线
            if ((t /= d / 2) < 1) {
                return c / 2 * t * t * t * t + b;
            }
            return - c / 2 * ((t -= 2) * t * t * t - 2) + b;
        },
        elasticIn: function (t, b, c, d, a, p) { //正弦衰减曲线(弹动渐入)
            if (t === 0) {
                return b;
            }
            if ((t /= d) == 1) {
                return b + c;
            }
            if (!p) {
                p = d * 0.3;
            }
            if (!a || a < Math.abs(c)) {
                a = c;
                var s = p / 4;
            } else {
                var s = p / (2 * Math.PI) * Math.asin(c / a);
            }
            return - (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
        },
        elasticOut: function (t, b, c, d, a, p) { //正弦增强曲线(弹动渐出)
            if (t === 0) {
                return b;
            }
            if ((t /= d) == 1) {
                return b + c;
            }
            if (!p) {
                p = d * 0.3;
            }
            if (!a || a < Math.abs(c)) {
                a = c;
                var s = p / 4;
            } else {
                var s = p / (2 * Math.PI) * Math.asin(c / a);
            }
            return a * Math.pow(2, - 10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
        },
        elasticBoth: function (t, b, c, d, a, p) {
            if (t === 0) {
                return b;
            }
            if ((t /= d / 2) == 2) {
                return b + c;
            }
            if (!p) {
                p = d * (0.3 * 1.5);
            }
            if (!a || a < Math.abs(c)) {
                a = c;
                var s = p / 4;
            }
            else {
                var s = p / (2 * Math.PI) * Math.asin(c / a);
            }
            if (t < 1) {
                return - 0.5 * (a * Math.pow(2, 10 * (t -= 1)) *
                        Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
            }
            return a * Math.pow(2, - 10 * (t -= 1)) *
                    Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b;
        },
        backIn: function (t, b, c, d, s) { //回退加速(回退渐入)
            if (typeof s == 'undefined') {
                s = 1.70158;
            }
            return c * (t /= d) * t * ((s + 1) * t - s) + b;
        },
        backOut: function (t, b, c, d, s) {
            if (typeof s == 'undefined') {
                s = 3.70158; //回缩的距离
            }
            return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
        },
        backBoth: function (t, b, c, d, s) {
            if (typeof s == 'undefined') {
                s = 1.70158;
            }
            if ((t /= d / 2) < 1) {
                return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
            }
            return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
        },
        bounceIn: function (t, b, c, d) { //弹球减振(弹球渐出)
            return c - Tween['bounceOut'](d - t, 0, c, d) + b;
        },
        bounceOut: function (t, b, c, d) {
            if ((t /= d) < (1 / 2.75)) {
                return c * (7.5625 * t * t) + b;
            } else if (t < (2 / 2.75)) {
                return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;
            } else if (t < (2.5 / 2.75)) {
                return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;
            }
            return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;
        },
        bounceBoth: function (t, b, c, d) {
            if (t < d / 2) {
                return Tween['bounceIn'](t * 2, 0, c, d) * 0.5 + b;
            }
            return Tween['bounceOut'](t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
        }
    }
    function css(obj, attr) {
        return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj) [attr]
    }
</script>
</html>

移动Web前端开发资源整合

<h2>meta篇</h2>
<h3>1.视窗宽度</h3>
<style>
.codex{padding: 2px 4px;
color: #d14;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;}
</style>

<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>

其中 width=device-width 是设置视窗宽度为设备视窗宽度,还可以固定宽度,例如: width=640 则是640px的宽度(常见于微信);


initial-scale=1.0 :设置缩放比例为1.0;


minimum-scale=1.0maximum-scale=1.0 :最小缩放比例和最大缩放比例;


user-scalable=no :禁止用户自由缩放,user-scalable 默认值为 yes 。


提示:刚刚那个是带全部参数的,一般常用的,有 user-scalable=no 就不用使用 minimum-scale=1.0maximum-scale=1.0 来强制禁止缩放了。

<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"/>

<h3>2.自动识别格式</h3>

<meta name="format-detection" content="telephone=no"/>

content 里面的参数:telephone=no 是禁止浏览器自动识别手机号码,email=no 是禁止浏览器自动识别Email。


<h3>3.完整模板</h3>

<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"/>
<meta name="format-detection" content="telephone=no"/>
<meta name="format-detection" content="email=no"/>

<h2>CSS篇</h2>

content 里面的参数:telephone=no 是禁止浏览器自动识别手机号码,email=no 是禁止浏览器自动识别Email。

3.完整模板

<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"/>
<meta name="format-detection" content="telephone=no"/>
<meta name="format-detection" content="email=no"/>
CSS篇

body {
    font-family: "Helvetica Neue", Helvetica, STHeiTi, sans-serif; /*使用无衬线字体*/
}

a, img {
    -webkit-touch-callout: none; /*禁止长按链接与图片弹出菜单*/
}

html, body {
    -webkit-user-select: none; /*禁止选中文本*/
    user-select: none;
}

button,input,optgroup,select,textarea {
    -webkit-appearance:none; /*去掉webkit默认的表单样式*/
}

a,button,input,optgroup,select,textarea {
    -webkit-tap-highlight-color:rgba(0,0,0,0); /*去掉a、input和button点击时的蓝色外边框和灰色半透明背景*/
}

input::-webkit-input-placeholder {
    color:#ccc; /*修改webkit中input的planceholder样式*/
}

input:focus::-webkit-input-placeholder {
    color:#f00; /*修改webkit中focus状态下input的planceholder样式*/
}

body {
    -webkit-text-size-adjust: 100%!important; /*禁止IOS调整字体大小*/
}

input::-webkit-input-speech-button {
    display: none; /*隐藏Android的语音输入按钮*/
}

<h2>Flex基础篇</h2>

这里假设flex容器为 .box ,项目为.item


<h3>1.定义容器为flex布局</h3>

.box{
    display: -webkit-flex; /*webkit*/
    display: flex;
}

/*行内flex*/
.box{
    display: -webkit-inline-flex; /*webkit*/
    display:inline-flex;
}
``
<h3>2.容器样式</h3>

.box{

flex-direction: row | row-reverse | column | column-reverse;
/*主轴方向:左到右(默认) | 右到左 | 上到下 | 下到上*/

flex-wrap: nowrap | wrap | wrap-reverse;
/*换行:不换行(默认) | 换行 | 换行并第一行在下方*/

flex-flow: <flex-direction> || <flex-wrap>;
/*主轴方向和换行简写*/

justify-content: flex-start | flex-end | center | space-between | space-around;
/*主轴对齐方式:左对齐(默认) | 右对齐 | 居中对齐 | 两端对齐 | 平均分布*/

align-items: flex-start | flex-end | center | baseline | stretch;
 /*交叉轴对齐方式:顶部对齐(默认) | 底部对齐 | 居中对齐 | 上下对齐并铺满 | 文本基线对齐*/

align-content: flex-start | flex-end | center | space-between | space-around | stretch;
/*多主轴对齐:顶部对齐(默认) | 底部对齐 | 居中对齐 | 上下对齐并铺满 | 上下平均分布*/

}

<h3>3.项目样式</h3>

.item{

order: <integer>;
/*排序:数值越小,越排前,默认为0*/

flex-grow: <number>; /* default 0 */
/*放大:默认0(即如果有剩余空间也不放大,值为1则放大,2是1的双倍大小,以此类推)*/

flex-shrink: <number>; /* default 1 */
/*缩小:默认1(如果空间不足则会缩小,值为0不缩小)*/

flex-basis: <length> | auto; /* default auto */
/*固定大小:默认为0,可以设置px值,也可以设置百分比大小*/

flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
/*flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto,*/

align-self: auto | flex-start | flex-end | center | baseline | stretch;
/*单独对齐方式:自动(默认) | 顶部对齐 | 底部对齐 | 居中对齐 | 上下对齐并铺满 | 文本基线对齐*/

}

<h2>小技巧篇</h2>
<h3>1.自定义苹果图标</h3>
<p>在网站文件根目录放一个<span class='codex'> apple-touch-icon.png </span>文件,苹果设备保存网站为书签或桌面快捷方式时,就会使用这个文件作为图标,文件尺寸建议为:180px × 180px。</p>
<h3>2.自定义favicon:</h3>

<link rel="icon" href="favicon.ico" mce_href="favicon.ico" type="image/x-icon">

<h3>3.定义浏览器点击行为:</h3>

打电话给:020-10086
发短信给: 10086
发送邮件: me@22278.club

<h3>4.定义上传文件类型和格式</h3>

<input type=file accept="image/*">

<p>上面的文件上传框中,<span class='codex'> accept</span> 可以限制上传文件的类型,参数为 image/* 是所有图片类型,点击会弹出图库,也可以指定图片格式,参数设置成<span class='codex'>  image/png</span> 则可以限制图片类型为png;参数如果为<span class='codex'>   video/*</span> 则是选择视频的意思;accept 还可以设置多个文件格式,语法为<span class='codex'>  accept="image/gif, image/jpeg"</span> ;</p>
<h3>5.使用box-shadow改变(挡住)表单自动填充后的黄色</h3>

input:-webkit-autofill, textarea:-webkit-autofill, select:-webkit-autofill{

box-shadow:inset 0 0 0 1000px #fff;

}

<h3>6.用CSS实现省略号文字截断</h3>

white-space: nowrap;
text-overflow: ellipsis;


感谢来源:http://www.ccwebsite.com/development-of-resource-integration-in-mobile-terminal/

零JS筆記 | 三角函数

函數:每一個變量都有對應的值稱之為函數


Math.pow(a,b) 表示ab</sup


Math.sqrt(a),表示a的開方,無法開多次方


a2+b2=c2


iMac底部菜單


See the Pen PPENEj by elmok (@elmok) on CodePen.


<script async src="//assets.codepen.io/assets/embed/ei.js"></script>



三角函数:Math.sin(弧度)、Math.cos(弧度)、Math.tan(弧度),即三角函数括号里以弧度为单位;


360o == 2π弧度; 所以,1弧度 = 180/π角度,1角度 = π/180弧度,记忆:弧度 > 角度


角度转弧度: π/180 × 角度


弧度变角度: 180/π × 弧度


sin = a/c;cos = b/c; tan = a/b


圆的周长:l = 2π*r


弧长等于半径的弧,其所对的圆心角为1弧度,所以: 弧长=nπr/180,在这里n就是角度数,即圆心角n所对应的弧长


一周的弧度数为2πr/r=2π,360°角=2π弧度,因此,1弧度约为57.3°,即57°17'44.806'',1°为π/180弧度,近似值为0.01745弧度,周角为2π弧度,平角(即180°角)为π弧度,直角为π/2弧度。

//角度转弧度,30度角转弧度,30*π/180
Math.sin(30 * Math.PI/180)

//上下比,角度对应π,弧度对应180


圓周運動,右水平線開始運動;

window.onload = function(){
    var oDiv = document.getElementById('div1');
    var r = 100;
    var x = 700;
    var y = 300;
    var num = 0;
    setInterval(function(){
        num++
        //Math.sin( num*Math.PI/180 ) = a/r;
        //Math.cos( num*Math.PI/180 ) = b/r;
        
        var a = Math.sin( num*Math.PI/180 ) * r; //顺时针时,距离中心点的top值越来越远
        var b = Math.cos( num*Math.PI/180 ) * r; //顺时针时,距离中心点的left值越来越近;

        oDiv.style.left = x + b + 'px';
        oDiv.style.top = y + a + 'px';
        
        var oBox = document.createElement('div');
        oBox.className = 'box';
        document.body.appendChild( oBox );
        
        oBox.style.left = oDiv.offsetLeft + 'px';
        oBox.style.top = oDiv.offsetTop + 'px';
    },300);
};
#div1{ width:20px; height:20px; background:red; position:absolute; left:800px; top:300px;}
.box{ border:1px #000 solid; position:absolute;}

围绕y轴,在x轴平面上做运动,并且有z轴半径r;所以top值不变,改变的是left值与宽高,形成视觉差,近大远小运动

window.onload = function(){
    var oDiv = document.getElementById('div1');
    var r = 100;
    var x = 700;
    var y = 300;
    var num = 0;
    setInterval(function(){
        num++
        //Math.sin( num*Math.PI/180 ) = a/r;
        //Math.cos( num*Math.PI/180 ) = b/r;

        //围绕y轴,在x轴平面上做运动,并且有z轴半径r;所以top值不变,改变的是left值与宽高,形成视觉差,近大远小运动
        
        var a = Math.sin( num*Math.PI/180 ) * r;
        var b = Math.cos( num*Math.PI/180 ) * r;

        oDiv.style.left = x + b + 'px';
        //oDiv.style.top = y + a + 'px';
        
        oDiv.style.width = a/100*30 + 50 + 'px'; //a最大100,起点50,注意理解
        oDiv.style.height = a/100*30 + 50 + 'px';

    },8);
};

圆心随鼠标移动方向移动;

var box = document.querySelector('.box')
var ege = document.querySelector('.ege')
var r = 50;
var L = 400
var T = 400
/*     -
     *     \
           \
    - ------------  +
           \
           \
    *      +
    * */
document.onmousemove = function (e) {
  var e = e || event;
  var x = e.clientX;
  var y = e.clientY;
  var a = Math.abs(x - (L + ege.parentNode.offsetLeft)) //为算角度
  var b = Math.abs(y - (T + ege.parentNode.offsetTop)) //大角与小角 角度一样
  var changeX = 0;
  var changeY = 0;
  if (x > L + ege.parentNode.offsetLeft && y < T + ege.parentNode.offsetTop) {
    changeX = Math.sin(Math.atan(b / a)) * r
    changeY = Math.cos(Math.atan(b / a)) * - r
  } 
  else if (x > L + ege.parentNode.offsetLeft && y > T + ege.parentNode.offsetTop) {
    changeX = Math.sin(Math.atan(b / a)) * r
    changeY = Math.cos(Math.atan(b / a)) * r
  } 
  else if (x < L + ege.parentNode.offsetLeft && y > T + ege.parentNode.offsetTop) {
    changeX = Math.sin(Math.atan(b / a)) * - r
    changeY = Math.cos(Math.atan(b / a)) * r
  } 
  else if (x < L + ege.parentNode.offsetLeft && y < T + ege.parentNode.offsetTop) {
    changeX = Math.sin(Math.atan(b / a)) * - r
    changeY = Math.cos(Math.atan(b / a)) * - r
  }
  ege.style.left = changeX + 'px'
  ege.style.top = changeY + 'px'
}

使用Math.atan2(y,x),以原点为基础,任意一点到原点x轴的夹角;值范围为-PI - PI,换角度即:-180 - 180



一图了然,所以改写为

var ev = ev || window.event;
change(oDiv2, ev.clientX, ev.clientY, L2, T2);
change(oDiv3, ev.clientX, ev.clientY, L3, T3);
function change(obj, x, y, l, t) {
  var changeX = 0;
  var changeY = 0;

  var a = x - (obj.offsetLeft + obj.parentNode.offsetLeft)    //方向 右+ 左- 上 + 下-
  var b = - (y - (obj.offsetTop + obj.parentNode.offsetTop))

  var ifm = Math.atan2(b, a) * 180 / Math.PI

  if (0 < ifm < 90) {
    changeX = Math.sin(Math.atan2(b, a)) * r
    changeY = Math.cos(Math.atan2(b, a)) * r
  } 
  else if (90 < ifm < 180) {
    changeX = Math.sin(Math.atan2(b, - a)) * r
    changeY = Math.cos(Math.atan2(b, - a)) * r
  } 
  else if (0 > ifm > - 90) {
    changeX = Math.sin(Math.atan2( - b, a)) * r
    changeY = Math.cos(Math.atan2( - b, a)) * r
  } 
  else if ( - 90 > ifm > - 180) {
    changeX = Math.sin(Math.atan2( - b, - a)) * r
    changeY = Math.cos(Math.atan2( - b, - a)) * r
  }

  obj.style.left = l + changeX + 'px';
  obj.style.top = t + changeY + 'px';
}


反正弦,反余弦 Math.asin(x); Math.acos(x) 求度数函数


正常sin30度=1/2 arcsin2/1=30度

cos60度=1/2 arccos1/2=30度



<style>

table{border-collapse: collapse;width:95%}
table td{border:1px solid #ddd;padding:5px 10px}
table th{border:1px solid #ddd;padding:5px 10px}

</style>

Math 对象属性

属性 描述
E 返回算术常量 e,即自然对数的底数(约等于2.718)。
LN2 返回 2 的自然对数(约等于0.693)。
LN10 返回 10 的自然对数(约等于2.302)。
LOG2E 返回以 2 为底的 e 的对数(约等于 1.414)。
LOG10E 返回以 10 为底的 e 的对数(约等于0.434)。
PI 返回圆周率(约等于3.14159)。
SQRT1_2 返回返回 2 的平方根的倒数(约等于 0.707)。
SQRT2 返回 2 的平方根(约等于 1.414)。

Math 对象方法

方法 描述
abs(x) 返回数的绝对值。
acos(x) 返回数的反余弦值。
asin(x) 返回数的反正弦值。
atan(x) 以介于 -PI/2 与 PI/2 弧度之间的数值来返回 x 的反正切值。
atan2(y,x) 返回从 x 轴到点 (x,y) 的角度(介于 -PI/2 与 PI/2 弧度之间)。
ceil(x) 对数进行上舍入。
cos(x) 返回数的余弦。
exp(x) 返回 e 的指数。
floor(x) 对数进行下舍入。
log(x) 返回数的自然对数(底为e)。
max(x,y) 返回 x 和 y 中的最高值。
min(x,y) 返回 x 和 y 中的最低值。
pow(x,y) 返回 x 的 y 次幂。
random() 返回 0 ~ 1 之间的随机数。
round(x) 把数四舍五入为最接近的整数。
sin(x) 返回数的正弦。
sqrt(x) 返回数的平方根。
tan(x) 返回角的正切。
toSource() 返回该对象的源代码。
valueOf() 返回 Math 对象的原始值。

零JS筆記 | javascript運動 | 时间版

jq的animate是典型的时间版框架 默認400ms


如中间放大,改width,height,left,top值

sMove2(this,{width:200,height:200,left:150,top:150})

出现的bug,快结束时会抖动,速度没变,但移动距离变,所以时间上先后到达存在问题;


时间版算法根据Tween算法而来;


参考:http://www.cnblogs.com/bluedream2009/archive/2010/06/19/1760909.html


初始化: t = 時間,【可變】,b,初始值,c改變量,d:總時間 return目標點


如:div初始100,2s内变化到200,则,t = 0~2; b:100,c:200-100,d:2s;

var Tween = {
    linear: function (t, b, c, d){  //匀速  
      return c*t/d + b;
    },
    ....

因为可能多个值,所以设置iCur变量为{},然后再for循环,初始化一0,判断是否opacity,初始化二:获取传值数据;

function tMove(obj, json,times,fx,fn) {
    var iCur = {};//不變,不能寫在定時器裏  b
    for(var attr in json){
        iCur[attr] = 0;
        if(attr=='opacity'){
            iCur[attr] = Math.round(getStyle(obj.attr)*100)
        }
        else{
            iCur[attr]=parseInt(getStyle(obj.attr));
        }
    }
    clearInterval(obj._t)
    obj._t = setInterval(function () {
        for(var attr in json){
            var value = Tween[fx](t,b,c,d) //目的,通過js獲取tbcd值
            if(attr == 'opacity'){
                obj.style.opacity = value/100;
                obj.style.filter = 'alpha(opacity='+value+')';

            }
            else{
                obj.style[attr] = value +'px'  //value是不断变化的值,即Tween return回来的结果;
            }
        }
    },13)
}

以上说明即目的:获取在Tween内,tbce参数的值,之后再返回结果给value;


注意:设置定时器时,还需要一个循环;

function tMove(obj, json, times, fx, fn) {
    if (typeof times == 'undefined') {
        times = 400;
        fx = 'linear';
    }
    if (typeof times == 'string') {
        if (typeof fx == 'function') {
            fn = fx;
        }
        fx = times;
        times = 400;
    }
    else if (typeof times == 'function') {
        fn = times;
        times = 400;
        fx = 'linear';
    }
    else if (typeof times == 'number') {
        if (typeof fx == 'function') {
            fn = fx;
            fx = 'linear';
        }
        else if (typeof fx == 'undefined') {
            fx = 'linear';
        }
    }
    var iCur = {
    }; //不變,不能寫在定時器裏  b
    for (var attr in json) {
        iCur[attr] = 0;
        if (attr == 'opacity') {
            iCur[attr] = Math.round(css(obj, attr) * 100);
        }
        else {
            iCur[attr] = parseInt(css(obj, attr));
        }
    }
    var startTime = now();
    clearInterval(obj._t);
    obj._t = setInterval(function () {
        var changeTime = now();
        var t = times - Math.max(0, startTime - changeTime + times);
        //在time的範圍內越來越小  2000-0;
        for (var attr in json) {
            var value = Tween[fx](t, iCur[attr], json[attr] - iCur[attr], times); //目的,通過js獲取tbcd值
            if (attr == 'opacity') {
                obj.style.opacity = value / 100;
                obj.style.filter = 'alpha(opacity=' + value + ')';
            }
            else {
                obj.style[attr] = value + 'px';
            }
        }
        if (t == times) {
            clearInterval(obj._t);
            fn && fn.call(obj);
        }
    }, 13)
}
function now() {
    return (new Date()).getTime();
}
var Tween = {
    linear: function (t, b, c, d) { //匀速
        return c * t / d + b;
    },
    easeIn: function (t, b, c, d) { //加速曲线
        return c * (t /= d) * t + b;
    },
    easeOut: function (t, b, c, d) { //减速曲线
        return - c * (t /= d) * (t - 2) + b;
    },
    easeBoth: function (t, b, c, d) { //加速减速曲线 缓冲
        if ((t /= d / 2) < 1) {
            return c / 2 * t * t + b;
        }
        return - c / 2 * ((--t) * (t - 2) - 1) + b;
    },
    easeInStrong: function (t, b, c, d) { //加加速曲线
        return c * (t /= d) * t * t * t + b;
    },
    easeOutStrong: function (t, b, c, d) { //减减速曲线
        return - c * ((t = t / d - 1) * t * t * t - 1) + b;
    },
    easeBothStrong: function (t, b, c, d) { //加加速减减速曲线
        if ((t /= d / 2) < 1) {
            return c / 2 * t * t * t * t + b;
        }
        return - c / 2 * ((t -= 2) * t * t * t - 2) + b;
    },
    elasticIn: function (t, b, c, d, a, p) { //正弦衰减曲线(弹动渐入)
        if (t === 0) {
            return b;
        }
        if ((t /= d) == 1) {
            return b + c;
        }
        if (!p) {
            p = d * 0.3;
        }
        if (!a || a < Math.abs(c)) {
            a = c;
            var s = p / 4;
        } else {
            var s = p / (2 * Math.PI) * Math.asin(c / a);
        }
        return - (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
    },
    elasticOut: function (t, b, c, d, a, p) { //正弦增强曲线(弹动渐出)
        if (t === 0) {
            return b;
        }
        if ((t /= d) == 1) {
            return b + c;
        }
        if (!p) {
            p = d * 0.3;
        }
        if (!a || a < Math.abs(c)) {
            a = c;
            var s = p / 4;
        } else {
            var s = p / (2 * Math.PI) * Math.asin(c / a);
        }
        return a * Math.pow(2, - 10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
    },
    elasticBoth: function (t, b, c, d, a, p) {
        if (t === 0) {
            return b;
        }
        if ((t /= d / 2) == 2) {
            return b + c;
        }
        if (!p) {
            p = d * (0.3 * 1.5);
        }
        if (!a || a < Math.abs(c)) {
            a = c;
            var s = p / 4;
        }
        else {
            var s = p / (2 * Math.PI) * Math.asin(c / a);
        }
        if (t < 1) {
            return - 0.5 * (a * Math.pow(2, 10 * (t -= 1)) *
                    Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
        }
        return a * Math.pow(2, - 10 * (t -= 1)) *
                Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b;
    },
    backIn: function (t, b, c, d, s) { //回退加速(回退渐入)
        if (typeof s == 'undefined') {
            s = 1.70158;
        }
        return c * (t /= d) * t * ((s + 1) * t - s) + b;
    },
    backOut: function (t, b, c, d, s) {
        if (typeof s == 'undefined') {
            s = 3.70158; //回缩的距离
        }
        return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
    },
    backBoth: function (t, b, c, d, s) {
        if (typeof s == 'undefined') {
            s = 1.70158;
        }
        if ((t /= d / 2) < 1) {
            return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
        }
        return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
    },
    bounceIn: function (t, b, c, d) { //弹球减振(弹球渐出)
        return c - Tween['bounceOut'](d - t, 0, c, d) + b;
    },
    bounceOut: function (t, b, c, d) {
        if ((t /= d) < (1 / 2.75)) {
            return c * (7.5625 * t * t) + b;
        } else if (t < (2 / 2.75)) {
            return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;
        } else if (t < (2.5 / 2.75)) {
            return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;
        }
        return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;
    },
    bounceBoth: function (t, b, c, d) {
        if (t < d / 2) {
            return Tween['bounceIn'](t * 2, 0, c, d) * 0.5 + b;
        }
        return Tween['bounceOut'](t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
    }
}
function css(obj, attr) {
    return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj) [attr]
}

See the Pen vNWQej by elmok (@elmok) on CodePen.


<script async src="//assets.codepen.io/assets/embed/ei.js"></script>



在瀏覽器中,若定時器處於運動狀態時切換到其他頁面,如最小化,切換到其他標籤等操作,瀏覽器會默認將定時器走得很慢,可能出現bug,可使用window.onfocus && window.onblur解決;按實際情獎況而訂;




不可避免的JQ animate()擴展

$(function () {
$('#div1').click(function () {
    $(this).animate({width:200,height:200},2000,'bounceIn')
})
$.extend(jQuery.easing,{
    easeIn: function(x,t, b, c, d){  //加速曲线
        return c*(t/=d)*t + b;
    },
    easeOut: function(x,t, b, c, d){  //减速曲线
        return -c *(t/=d)*(t-2) + b;
    },
    easeBoth: function(x,t, b, c, d){  //加速减速曲线
        if ((t/=d/2) < 1) {
            return c/2*t*t + b;
        }
        return -c/2 * ((--t)*(t-2) - 1) + b;
    },
    easeInStrong: function(x,t, b, c, d){  //加加速曲线
        return c*(t/=d)*t*t*t + b;
    },
    easeOutStrong: function(x,t, b, c, d){  //减减速曲线
        return -c * ((t=t/d-1)*t*t*t - 1) + b;
    },
    easeBothStrong: function(x,t, b, c, d){  //加加速减减速曲线
        if ((t/=d/2) < 1) {
            return c/2*t*t*t*t + b;
        }
        return -c/2 * ((t-=2)*t*t*t - 2) + b;
    },
    elasticIn: function(x,t, b, c, d, a, p){  //正弦衰减曲线(弹动渐入)
        if (t === 0) {
            return b;
        }
        if ( (t /= d) == 1 ) {
            return b+c;
        }
        if (!p) {
            p=d*0.3;
        }
        if (!a || a < Math.abs(c)) {
            a = c;
            var s = p/4;
        } else {
            var s = p/(2*Math.PI) * Math.asin (c/a);
        }
        return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
    },
    elasticOut: function(x,t, b, c, d, a, p){    //正弦增强曲线(弹动渐出)
        if (t === 0) {
            return b;
        }
        if ( (t /= d) == 1 ) {
            return b+c;
        }
        if (!p) {
            p=d*0.3;
        }
        if (!a || a < Math.abs(c)) {
            a = c;
            var s = p / 4;
        } else {
            var s = p/(2*Math.PI) * Math.asin (c/a);
        }
        return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
    },
    elasticBoth: function(x,t, b, c, d, a, p){
        if (t === 0) {
            return b;
        }
        if ( (t /= d/2) == 2 ) {
            return b+c;
        }
        if (!p) {
            p = d*(0.3*1.5);
        }
        if ( !a || a < Math.abs(c) ) {
            a = c;
            var s = p/4;
        }
        else {
            var s = p/(2*Math.PI) * Math.asin (c/a);
        }
        if (t < 1) {
            return - 0.5*(a*Math.pow(2,10*(t-=1)) *
                    Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
        }
        return a*Math.pow(2,-10*(t-=1)) *
                Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b;
    },
    backIn: function(x,t, b, c, d, s){     //回退加速(回退渐入)
        if (typeof s == 'undefined') {
            s = 1.70158;
        }
        return c*(t/=d)*t*((s+1)*t - s) + b;
    },
    backOut: function(x,t, b, c, d, s){
        if (typeof s == 'undefined') {
            s = 3.70158;  //回缩的距离
        }
        return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
    },
    backBoth: function(x,t, b, c, d, s){
        if (typeof s == 'undefined') {
            s = 1.70158;
        }
        if ((t /= d/2 ) < 1) {
            return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
        }
        return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
    },
    bounceIn: function(x,t, b, c, d){    //弹球减振(弹球渐出)
        return c - this['bounceOut'](x,d-t, 0, c, d) + b;
    },
    bounceOut: function(x,t, b, c, d){
        if ((t/=d) < (1/2.75)) {
            return c*(7.5625*t*t) + b;
        } else if (t < (2/2.75)) {
            return c*(7.5625*(t-=(1.5/2.75))*t + 0.75) + b;
        } else if (t < (2.5/2.75)) {
            return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b;
        }
        return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b;
    },
    bounceBoth: function(x,t, b, c, d){
        if (t < d/2) {
            return this['bounceIn'](x,t*2, 0, c, d) * 0.5 + b;
        }
        return this['bounceOut'](x,t*2-d, 0, c, d) * 0.5 + c*0.5 + b;
    }

})
})

零JQ筆記 | ajax

AJAX

callback返回三个参数,在load()方法中,只要请求完成,无法是否成功,callback即会被触发

$('#resText').load('test.html .para', function (responseText, textStatus, XMLHttpRequest) {
  console.log(responseText); //请求返回的内容
  console.log(textStatus); //请求状态:success,error
  console.log(XMLHttpRequest); //XMLHttpRequest对象
});

$.get()/$.post()
$.get(url ,data[,type])

$.get(url, 发送到服务器的key/v, 回调,服务器返回格式xml/html/script/json/text/_default)

发送到get1.php,发送的内容为:username/content/,要求服务器返回html格式;

$.get('get1.php', {
  username: $('#username').val(),
  content: $('#content').val()
}, function (data, textStatus) {
  $('#resText').html(data); // 把返回的数据添加到页面上
}
);

function (data, textStatus): data:返回的内容:xml/json/html等; testStatus: 请求状态:success/error/notmodified/timeout; 而且只有当数据成功返回success反才调用,注意与load()不一样;

data返回的数据内容如

返回内容 处理
html 可直接输出$(obj).html()
XML XML文档可使用常用的attr()/find()/filter()等处理
function (data, textStatus) {
  var username = $(data).find('comment').attr('username');
  var content = $(data).find('comment content').text();
  var txtHtml = '<div class=\'comment\'><h6>' + username + ':</h6><p class=\'para\'>' + content + '</p></div>';
  $('#resText').html(txtHtml); // 把返回的数据添加到页面上
}

</td>

</tr> 
<tr> 
 <td>json</td> 
 <td>json格式简洁,易读,对返回处理后输出html
function (data, textStatus) {
  var username = data.username;
  var content = data.content;
  var txtHtml = '<div class=\'comment\'><h6>' + username + ':</h6><p class=\'para\'>' + content + '</p></div>';
  $('#resText').html(txtHtml); // 把返回的数据添加到页面上
},
'json'); //要求服务器返回json格式

</td>

</tr> 

</tbody>
</table>


好处与利弊:html片段最简单;json数据重用、性能、大小、较好; xml远程应用程序未知时较好,适用于任何语言;



$.getScript('test.js')
当然,也有回调:

$.getScript('test.js',function(){
    $('#go').click(function(){
    .....
})
})



$.getJSON('test.json')
当然,也有回调:

$.getJSON('test.json',function(data){
   //data返回数据
})
})



通过$.getJSON得到的数据data,可使用$.each()来遍历[对象和数组]

$.each(data, function (i, elem) {
console.log(i); //i表示索引,elem表示值
console.log(elem['username']);
})
通过JSONP加载其它网站数据;跨域首选

$.getJSON('http://api...../',function(data){
   $.each(data[obj],function(i,elem){
        .....
        //i可作为判断条件,退出each循环,return false;
    })
})

底层$.ajax(options)方法

<style>

.ajax-tb-1 { border-collapse: collapse }
.ajax-tb-2{border-collapse: collapse}
.ajax-tb-2 td{border:1px solid #ddd;padding:5px 10px;line-height: 2;}
.ajax-tb-2 tr>td:nth-of-type(2){white-space: nowrap; }
.ajax-tb-1 td, .ajax-tb-1 th { border: 1px solid #ddd; padding: 5px 10px; line-height: 2; }

</style>

該方法只有一個參數,所有包含在$.ajav()裏,參數以key/value形式,所有參數除url外都是可選

參數名 類型 說明
url string 默認,發送,請求地址
type string post/get,默認get,注意put/delete部分瀏覽器不支持
data obj or string 發送到服務器的數據,如非字符串,則自動轉字符串形式 <br/>請求獎附加在url後,防止自動轉可查看processData選項,對象必須為key/value格式;<br/>例如 {fool:'bar1',foo2:'bar2'} ==>>&foo1=bar1&foo2=bar2 <br/>如果是數組,轉為不同值對應同一個名稱。 {foo:['bar1','bar2']}==>>&foo=bar1&foo=bar2
dataType string 預期服務器返回類型,不指定:自動按http包mime信息返回responseXML或responseText,並作為callback參數傳遞;可用類型:<br/>xml:返xml文檔,可用jq處理 <br/>html:純html信息,包含的script標籤會在插入dom時執行<br/>script:純js代碼,不自動緩存結果,除非設置cache,注意:遠程請求時所有跨域請求都轉為get請求 <br/>json:返回JSON數據;<br/>jsonp:使用JSONP形式調用函數時,如:myurl?callback=?,jq將自動替換後一個?為正確函數名 <br/>text:純txt字符串
beforeSend Function 發送前可修改XMLHttpRequst對象函數,如:添加算定義HTTP頭,在beforeSend中返回false可取消本次ajax請求,XMLHttpRequest對象是惟一請求;<br/> function(XMLHttpRequest){ this //調用本次ajax請求傳傳遞的options參數 }
complete Function 請求完成後回調,成功失敗都可調用;<br/>參數:XMLHttpRequest對像和一個描述成功請求類型的string, function(XMLHttpRequest,textStatus){ this //調用本次ajax請求傳傳遞的options參數 }
success Function 請求成功後callback <br/> 1).由服務器返回,按給的dataType參數進行處理後數據 ; <br/>2).描述狀態string; <br/> function(data,textStatus){ data; //可能是xmlDoc,jsonObj,html,text等等, this; //調用本次ajax請求傳傳遞的options參數 }
error Function 請求失敗時調用,3參數: function(XMLHttpRequest ,textStatus,errorThrown){ //通常情況下textStatus和errorThown只有其中一個包含信息 this //調用本次ajax請求傳傳遞的options參數 }
global Boolean 默認true,表示是否觸發全局ajax事件,設置false將不觸發,AjaxStart或AjaxStop可用於控制各種Ajax事件;

代替$.getScript()

$(function () {
    $('send').click(function () {
        $.ajax({
            type:'GET',
            url:'test.js',
            dataType:'script'
        })
    })
})

代替$.getJSON()

$.ajax({
    type:'GET',
    url:'test.json',
    dataType:'json',
    success: function (data) {
        var html=''
        $.each(data, function (index,elems) {
            html +=index 
            +':' 
            +elems['username'] 
            +':' 
            +elems['content']
        })
        $('body').html(html)
    }
})

test.json

[
  {
    "username": "张三",
    "content": "沙发."
  },
  {
    "username": "李四",
    "content": "板凳."
  },
  {
    "username": "王五",
    "content": "地板."
  }
]



1、serialize()方法,表單序列化,所有元素必須設置name,使用name來獲取;

<form action="" id="f2">
    <p>user:<input type="text" name="user" id=""/></p>
    <p>password:<input type="password" name="pws" id=""/></p>
    <input type="checkbox" name="ck" id=""/>
    <input type="checkbox" name="ck2" id=""/>
    <input type="radio" name="rrr" id=""/>
    <input type="radio" name="rrr" id=""/>
    <input type="radio" name="rrr" id=""/>
    <p><input type="button" id="send2" value="提交"/></p>
</form>
$('#send2').click(function () {
    console.log($('#f2').serialize());
    console.log($('#f2').serializeArray()); //若使用serializeArray()輸出對像如下圖
})

輸出:user=elmok&pws=elmokpws&ck2=on&rrr=on

輸出對象:

所以可使用$.each()

var fdata = $('#f2').serializeArray(),
$.each(fdata ,function(i,elems){
    $('body').append(fdata.value + '')
})

例子:

<form id="form1" action="#">
    <p>评论:</p>
    <p>姓名: <input type="text" name="username" id="username" /></p>
    <p>内容: <textarea name="content" id="content"  rows="2" cols="20"></textarea></p>
    <p><input type="button" id="send" value="提交"/></p>
</form>
<div id="resText"></div>

為取得姓名和內容,必須將字段一個個添加到data參數中

$('#send').click(function () {
    $.get('get1.php',{
        username:$('#username').val(),
        content:$('#content').val()
    }, function (data, textStatus) {
        $('#resText').html(data)  //返回頁面
    })
})

少量可以,多則使用serialize()方法

$('#send').click(function () {
    $.get('get1.php',$('#form1').serialize(), function (data, textStatus) {
        $('#resText').html(data)
    })
})

需要注意:$.get()方法中,data參數不僅可使用映射方式:

{
username:$('#username').val(),
content:$('#content').val()
}

也可使用字符串[中文問題]方式:注意,字符串無{}號

$('#send').click(function () {
    $.get('get1.php',
 "username="+encodeURIComponent($('#username').val())+"&content="+encodeURIComponent($('#content').val())     
    , function (data, textStatus) {
        $('#resText').html(data)
    })
})



3、$.param()方法
serialize()方法核心,對一個arr或obj按照key/value進行序列化

var obj = {a:1,b:2,c:3}
var k = $.param(obj)
//輸出:a=1&b=2&c=3



jq中的ajax全局事件
加載中loading....提示,定義好
loading......

$("#loading").ajaxStart(function(){
  $(this).show();
});
$("#loading").ajaxStop(function(){
  $(this).hide();
});

其他地方使用,仍有效,因為是全局;

另外幾個方法


ajaxComplete(fn..):請求完成時執行;

ajaxError(fn..):發生錯誤時執行,捕捉到錯誤可作為最後一個參數傳遞;

ajaxSend(fn..):請求發送前執行;

ajaxSuccess(fn...):請求成功時執行;

1、jq1.5之前,如不想某個ajax請求受全局方法影響

$.ajax({
    url:'...',
    global:false
})

1、jq1.5之後,如不想某個ajax請求受全局方法影響,則在每次發送請求之前設置

$.ajaxPrefilter(function (options) {
    options.global = true;
})

零JS筆記 | javascript運動 | 弹性 | 碰撞

運動公式:


弹性:速度+=(目标点-当前值)/系数 必須是全局变量

速度*=摩擦系数[小于1]

缓冲:
var 速度 = (目标点-当前值)/系数 局部變量

速度取整

系數取值:
系数: 6,7,8
摩擦系数:0.75

運動的基本步驟:


1、清除定時器;

2、開定定時器:寫條件...

寫彈性運動步驟:


1)、写两个速度公式;

2)、写两个停止条件:速度的绝对值<=1,距离[目標點-本身位置]的绝对值<=1;

3)、修正偏差:距離 == 目標點;速度 ==0

function sMove() {
        clearInterval(_t)
        _t = setInterval(function () {
//1、写两个速度公式
        _speed+=(500-div.offsetLeft)/6
        _speed*=0.75
//2、写两个停止条件 速度的绝对值,距离的绝对值
        if(Math.abs(_speed)<=1 && Math.abs(500-div.offsetLeft)<=1){
        clearInterval(_t)
//3/修正偏差
         div.style.left = '500px'
         _speed = 0;
        }
        else{
        div.style.left = div.offsetLeft+_speed+'px'
        }
    }, 30)
}



首先,滾動歌詞的效果
1、定認兩個div,定位重疊

<div id="div1"><span>红眼睛幽幽的看着这孤城,如同苦笑挤出的高兴,浮华盛世做分手布景</span></div>
<div id="div2"><span>红眼睛幽幽的看着这孤城,如同苦笑挤出的高兴,浮华盛世做分手布景</span></div>

2、第一個div1定住不動;div2外層限制寬高加overflow:hidden; div2內層span設置定位,限制高,寬2000px;

#div2{color:#cd0000;height:36px;width:36px;overflow:hidden;}
#div2 span{position:absolute;left:0;top:0;width:2000px;height:20px}

3、理解,div2外層向左移動+1px/每次時,內層span2同時相反移動

setInterval(function(){
   div2.style.left = div2.offsetLeft+1+'px';
   span2.style.left = -div2.offsetLeft+'px';
},30)

so,彈性菜單的例子是:

1、佈局:mark為需要在上面運動的項;

<ul id="ul1">
    <li id="mark">
        <ul>
            <li>首页</li>
            <li>论坛</li>
            <li>视频</li>
            <li>留言</li>
        </ul>
    </li>
    <li class="box">首页</li>
    <li class="box">论坛</li>
    <li class="box">视频</li>
    <li class="box">留言</li>
</ul>

See the Pen gaGVEL by elmok (@elmok) on CodePen.


<script async src="//assets.codepen.io/assets/embed/ei.js"></script>

当attr = width || height 時,低IE會出現彈性過過界,不允許負值,即出現錯誤; 所以
var H = div.offsetHeight + _speed;
if(H<0){  //ie下元素的高度不能为负值;
    H=0;
}

弹性运动整合版

function sMove(obj, json, fn) {
    clearInterval(obj.timer);
    var json2 = copy(json);
    obj.timer = setInterval(function () {
        var bStop = true;
        for (var attr in json) {
            var iCur = 0;
            if (attr == 'opacity') {
                iCur = Math.round(parseFloat(getStyle(obj, attr)) * 100);
            } else {
                iCur = parseInt(getStyle(obj, attr));
            }
            json2[attr] += (json[attr] - iCur) / 6;
            json2[attr] *= 0.75;
            if (Math.abs(json2[attr]) < 1 && Math.abs(json[attr] - iCur) <= 1) {
                if (attr == 'opacity')
                {
                    obj.style.filter = 'alpha(opacity:' + (json[attr]) + ')';
                    obj.style.opacity = (json[attr]) / 100;
                }
                else
                {
                    obj.style[attr] = json[attr] + 'px';
                }
            } else {
                bStop = false;
                if (attr == 'opacity')
                {
                    obj.style.filter = 'alpha(opacity:' + (iCur + json2[attr]) + ')';
                    obj.style.opacity = (iCur + json2[attr]) / 100;
                }
                else
                {
                    obj.style[attr] = Math.round(iCur + json2[attr]) + 'px';
                }
            }
        }
        if (bStop) {
            clearInterval(obj.timer);
            fn && fn.call(obj)
        }
    }, 30);
};
function getStyle(obj, attr) {
    if (obj.currentStyle) {
        return obj.currentStyle[attr];
    } else {
        return getComputedStyle(obj, false) [attr];
    }
}
function copy(obj) {
    var o = {
    };
    for (var i in obj) {
        o[i] = 0;
    }
    return o;
}



碰撞运动,找到临界点,再确定运动方向,改对应的速度 ,將速度取反;

var _div = document.getElementById('div1')
var _speedX = 10;
var _speedY = 10;
sMove()
//碰撞运动,1、找到临界点,再确定运动方向,改对应的速度 (速度取反)
function sMove(){
setInterval(function () {
    var L = _div.offsetLeft +_speedX;
    var T = _div.offsetTop +_speedY;
    if(T>document.documentElement.clientHeight-_div.offsetHeight){
        T =document.documentElement.clientHeight-_div.offsetHeight
        _speedY *=-1
    }
    if(T<0){
        T=0;
        _speedY*=-1 //又变为正
    }
    if(L>document.documentElement.clientWidth-_div.offsetWidth){
        L =document.documentElement.clientWidth-_div.offsetWidth
        _speedX *=-1
    }
    if(L<0){
        L=0;
        _speedX*=-1 //又变为正
    }
    _div.style.left = L +'px'
    _div.style.top = T +'px'

},30)
}

自由落體運動、拋物線運動


自由落體: 只需改變top值,接觸到目標點後速度取反向上運動,再使用摩擦系數使速度停下來;

拋物線: 添加left方向速度及判定,摩擦系數使速度停下來,注意初始化目標位置及初始化速度;

See the Pen ojodqO by elmok (@elmok) on CodePen.


<script async src="//assets.codepen.io/assets/embed/ei.js"></script>

iphone拖動效果


首先,拖動

obj.onmousedown = function(e){
    var e = e || event;
    ....
    document.onmousemove = function(e){
        ...
    }
    document.onmouseup = function(e){
        document.onmousemove = document.onmouseup = null;
        ...
    }
    return false;
}

mousemove,鼠標移動的距離 == 元素left值移動的距離 ul1.style.left = e.clientX-disX + 'px'
mouseup時,元素需要移動的距離為一個li的距離,產生的效果由彈性公式生成;
當mousedown時存鼠標位置downX,與抬起時位置對比,小於走左,大於走右;
使用變量inow++ --

See the Pen KdyRrX by elmok (@elmok) on CodePen.


<script async src="//assets.codepen.io/assets/embed/ei.js"></script>

公告碰撞效果


See the Pen meqLgV by elmok (@elmok) on CodePen.


<script async src="//assets.codepen.io/assets/embed/ei.js"></script>

零JS筆記 | javascript運動 | 匀速 | 缓冲

運動基礎:勻速運動
運動框架實現:1、開始前,關閉已有定時器;2、檢測停止條件與執行運動對立;(if/else)

btn.onclick =function(){
    sMove()
}
function sMove(){
    clearInterval(_t)
    _t = setInterval(function () {
        if(div1.offsetLeft >= 500){
            clearInterval(_t)
        }
        else{
            div1.style.left = div1.offsetLeft+10+'px'
        }
    },30)
}

分享到:

See the Pen MavJVv by elmok (@elmok) on CodePen.


<script async src="//assets.codepen.io/assets/embed/ei.js"></script>

透明變化的問題 小數點精度問題:alert(0.1+0.2) //0.3000000000004 所以,操作須用整數; 透明度處理分IE及標準 ; 獲取透明度的值,不能直接使用obj.style.opacity,須使用
function css(obj,attr){
    return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj) [attr]
}

之後通過css()獲取透明度值再*100四舍五入轉整數;,所以是:

function sMove2(obj, _target, _speed) {
  clearInterval(_t)
  _t = setInterval(function () {
    var iCur = Math.round(css(obj, 'opacity') * 100)
    if (iCur == _target) {
      clearInterval(_t)
    } 
    else {
      obj.style.opacity = (iCur + _speed) / 100  //標準
      obj.style.filter = 'alpha(opacity=' + iCur + _speed + ')' //IE
    }
  }, 30)
}

使多物體能同時運動,技巧是更改定時器命名:obj._t 整合是:

function sMove2(obj, attr, _target, _speed) {
  clearInterval(obj._t)
  var iCur = 0;
  obj._t = setInterval(function () {
    if (attr == 'opacity') {                   //判斷是否透明
      iCur = Math.round(css(obj, attr) * 100)
    } 
    else {
      iCur = parseInt(css(obj, attr));
    }
    if (iCur == _target) {                    //判斷是否到結束點
      clearInterval(obj._t)
    } 
    else {                                   //未到結束點時
      if (attr == 'opacity') {                          //透明操作
        obj.style.opacity = (iCur + _speed) / 100
        obj.style.filter = 'alpha(opacity=' + iCur + _speed + ')'
      } 
      else {                                        //其他操作                
        obj.style[attr] = iCur + _speed + 'px'
      }
    }
  }, 30)
}
function css(obj, attr) {
  return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj) [attr]
}

使用多個值同時運動,比如,走width:200同時height:300; 所以獲取參數使用json,for in來操作

function sMove2(obj, json, _speed) {
  clearInterval(obj._t)
  var iCur = 0;
  obj._t = setInterval(function () {
    var on = true;
    //定時器每走一下,把要運動的屬性推進一次;
    for (var attr in json) {
      var _target = json[attr]
      if (attr == 'opacity') {
        iCur = Math.round(css(obj, attr) * 100)
      } 
      else {
        iCur = parseInt(css(obj, attr));
      }
      if (iCur !== _target) { //如果其中有一個屬性沒到,則on=false
        //什麼時候停定時器,所有屬性都運動到了
        on = false //記住這是寶時器,所有on的值在不斷改變,不存在駐內在需要變回true的情況,因為一開頭定義就是true;
        if (attr == 'opacity') {
          obj.style.opacity = (iCur + _speed) / 100
          obj.style.filter = 'alpha(opacity=' + iCur + _speed + ')'
        } 
        else {
          obj.style[attr] = iCur + _speed + 'px'
        }
      }
    }
    //注意要在for in外面看是否所有屬性都運動到了。

    if (on) {
      clearInterval(obj._t)
    }
  }, 30)
}

把運動使用.call()回調加上,即可在回調裏使用this

if (on) {
  clearInterval(obj._t)
  fn && fn.call(obj) //this指向,默認是window,所以指向調用的obj
}



缓冲运动,關鍵,速度怎麼算?

缓冲运动 与摩擦力的区别:可以精确的停到指定目标点 距离越远速度越大 速度由距离决定 速度=(目标值-当前值)/缩放系数 Bug:速度取整 值取整
//當速度小於0.5時,掛了。
console.log(div1.offsetLeft);
_speed = (500 - div1.offsetLeft) * 0.2

//所以需要的_speed小於0.5時,向上取整為1; 
_speed = _speed > 0 ? Math.ceil(_speed)  : Math.floor(_speed)

注意: css可以解析小數點,js會把當前值四舍五入運算;

所以整合是,速度參數不需要,因為算出來即可;

function sMove2(obj, json, fn) {
    clearInterval(obj._t);
    var iCur = 0;
    var _speed = 0;
    obj._t = setInterval(function() {
        var on = true;
        for ( var attr in json ) {
            var _target = json[attr];
            if (attr == 'opacity') { //opacity属性传值为0 - 100
                iCur = Math.round(css( obj, 'opacity' ) * 100);
            } else {
                iCur = parseInt(css(obj, attr));
            }
            _speed = ( _target - iCur ) / 8;
            _speed = _speed > 0 ? Math.ceil(_speed) : Math.floor(_speed);
            if (iCur != _target) {
                on = false;
                if (attr == 'opacity') {
                    obj.style.opacity = (iCur + _speed) / 100;
                    obj.style.filter = 'alpha(opacity='+ (iCur + _speed) +')';
                } else {
                    obj.style[attr] = iCur + _speed + 'px';
                }
            }
        }
        if (on) {
            clearInterval(obj._t);
            fn && fn.call(obj);
        }
    }, 30);
}

function css(obj, attr) {
    return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj) [attr]
}

下面是實例,多圖片殿開收縮:1、元素居中放大,寬高、定位都要改變,圖片放大1倍,則位移放大寬高的一半;

2、用js設置css樣式時,須注意問題,在同一個代碼塊中,有些css樣式的設置的權限要高於其他的樣式;解決:可放在不同代碼塊裏;

See the Pen PPKWLZ by elmok (@elmok) on CodePen.


<script async src="//assets.codepen.io/assets/embed/ei.js"></script>

帶運動的留言本、注意ul及li加overflow:hidden;否則運動會有問題;

_li.style.height = 0;
_li.style.opacity = 0; //因為要運動。所以先初始化為0;

See the Pen RWZKmw by elmok (@elmok) on CodePen.


<script async src="//assets.codepen.io/assets/embed/ei.js"></script>

返回頂部:如果是fixed定位則不需要算setTop值;使用absolute固定在右下角,須一直改變top值
setTop()方法,當前的style.top = 當前視口高度 + 滾動條 - 元素本身高度
iCur表示當前變化的值:Math.floor((0 - iCur) / 8);當前變化的值到頂部0 來計算出speed
iCur== 0,到頂部了,清除,未到頂部,則滾動條高度:document.documentElement.scrollTop = document.body.scrollTop = iCur + _speed;

var div = document.getElementById('div1')
var _t = null;
var b = 1;
setTop();
window.onscroll = function () {
  if (b != 1) { //如果==1,那麼當前scroll事件是被定時器所觸發的,所果不等於1,即非定時器的其他任何一個操作觸發
    clearInterval(_t)
  }
  b = 2;
  setTop();
}
div.onclick = function () {
  clearInterval(_t)
  var iCur = _speed = 0;
  _t = setInterval(function () {
    iCur = document.documentElement.scrollTop || document.body.scrollTop
    _speed = Math.floor((0 - iCur) / 8); //其實還是算speed
    if (iCur == 0) {
      clearInterval(_t)
    } else {
      document.documentElement.scrollTop = document.body.scrollTop = iCur + _speed;
    }
    b = 1;
  }, 30)
}
function setTop() {
  var scrollTop = document.documentElement.scrollTop || document.body.scrollTop
  div.style.top = scrollTop + document.documentElement.clientHeight - div.offsetHeight + 'px'
}

圖片預加載


當給Image()對象的src屬性一個url時,則對象去加載,加載完成保存在瀏覽器的cache裏,下次若再用,則直接從cache文件讀取;所以速度很快 ,並且節約資源;使用Image()對像,把需要的圖片地址處理後預加載到瀏覽器中;在頁面上再調用相同地址時,瀏覽器會自動先從cache裏讀取;

兩個事件:onload 當資源加載完成時,onerror,當資源加載失敗時

var oImage = new Image()  //對象
var img = document.getElementById('img')  //頁面元素
oImage.src = 'http://i1.download.fd.pchome.net/1.jpg'  //對象加載
oImage.onload = function () {
  document.onclick = function () {
    img.src = 'http://i1.download.fd.pchome.net/1.jpg'   //頁面請求
  }
}
function xl() {
  oimg.src = arr[icur]  //頁面上的圖片用數組先存起
  oimg.onload = function () {
    icur++
    if (icur < arr.length) { //如果小於,證明未下載完,則再次調用xl()
      xl() //遞歸
    }
    document.title = icur + '/' + arr.length;
  }
}

按需加載


初始化時:

 <img _src="t5.JPG" src="white.png" alt=""/>

當obj的top值 < 滾動條 + 視口高度;把_src的值附給src;
避免重覆加載,可以在賦值後的img上加自定義屬性 _img[i].isload = true; 如果isload =false則加載,=true則不重覆加載

window.onload = function () {
  var _ul = document.getElementById('ul1')
  var _img = _ul.getElementsByTagName('img')
  showImage()
  window.onscroll = function () {
    showImage()
  }
  function showImage() {
    var scrollTop = document.documentElement.scrollTop || document.body.scrollTop
    for (var i = 0; i < _img.length; i++) {
    //注意前後順序
      if (!_img[i].isload && getTop(_img[i]) < scrollTop + document.documentElement.clientHeight) {
        _img[i].src = _img[i].getAttribute('_src')
        _img[i].isload = true; //這種方法並非最優,for循環還要跑
      }
    }
  }
  function getTop(obj) {
    var itop = 0;
    while (obj) {
      itop += obj.offsetTop;
      obj = obj.offsetParent;
    }
    return itop;
  }
}

零JS筆記 | 正則基礎

部分常用正則:

//QQ驗證:
var re = /^[1-9]\d{4,11}$/

//去空格:
var re = /^\s+|\s+$/g;

//匹配中文:
[\u4e00-\u9fa5]

//行首行尾空格
^\s*|\s*$

//Email:
^\w+@[a-z0-9]+(\.[a-z]+){1,3}$

//网址:
[a-zA-z]+://[^\s]*

//QQ号:
[1-9][0-9]{4,9}

//邮政编码:
[1-9]\d{5}

//身份证:
[1-9]\d{14}|[1-9]\d{17}|[1-9]\d{16}x

ver re = {
    qq:[1-9][0-9]{4,9},
    email:^\w+@[a-z0-9]+(\.[a-z]+){1,3}$,
    number:/\d+/,
    url:[a-zA-z]+://[^\s]*,
    nospace:^\s*|\s*$,
    postalcode:[1-9]\d{5},
    icard:[1-9]\d{14}|[1-9]\d{17}|[1-9]\d{16}x
}

re.email




例如分析:

abcd12@163qq.com

^w+@[a-z0-9]+(.[a-z]+){1,3}$

^w+ :可出現多位字符

@:匹配@

[a-z0-9]+ :可出現多次字符

(.[a-z]+) :分組,.匹配真正的. [a-z]:出現net com 一個整體;

{1,3}$: 再+量詞表示如.com.cn .cn.net等等


普通查看字符串裏的數字

str = 'weirup123skjdlj890lkjd12kldk899'
console.log(findNum(str));
function findNum(str) {
  var arr = [
  ]
  var tmp = ''
  for (var i = 0; i < str.length; i++) {
    if (str.charAt(i) <= '9' && str.charAt(i) >= '0') {
      //  arr.push(str.charAt(i))
      tmp += str.charAt(i)
    } 
    else {
      if (tmp) {
        arr.push(tmp);
        tmp = '';
      }
    }
  }
  if (tmp) {
    arr.push(tmp)
    tmp = '';
  }
  return arr;
}
var re = /\d+/g; //找出數字;
var re = /\D+/g; //找出字母;
console.log(str.match(re));

<style>
.reg-tb{

width:100%;border-collapse: collapse

}
.reg-tb td{border:1px solid #ccc;padding:5px;}
.reg-tb tr>td:first-child{min-width: 100px;

text-align: center;}

</style>

test 匹配返回真假 寫法:re.test(str)
search 成功返回位置,匹配失败,就返回-1,像indexOf 寫法:str.search(re)
replace 返回替换后的字符串 寫法:str.replace(re,newstr),replace : 第二个参数;可以是字符串,也可以是一个回调函数
match 返回匹配数组 寫法:str.search(re)

轉義字符:

n 換行
r 製表
t 回車
s 空格
S 非空格
d 數字
D 非數字
w 字符 (字母、數字、下劃線_)
W 非字符 (特殊字符、漢字等)
b 独立的部分(起始、结束、空格)
B 非独立的部分

小記錄

i i——ignore 正则中的默认:是区分大小写; 如果不区分大小写的话,在正则的最后加标识 i (不区分大小写)
g 全局匹配:g——global;正则默认:正则匹配成功就会结束,不会继续匹配 如果想全部查找,就要加标识 g(全局匹配)
+ 量詞;匹配不确定的位置 + : 至少出现一次,如d+,即至少匹配多次數字,如果連接數字則為一個整體
{} 量詞;不確定次數:{4,7}:最少出現4次,最多出現7次;{4,}最少出現4次;{4}:剛好出現4次;var re = /ddd/; === /d{3}/;
+ = {1,}
? ? 重複零次或1次;var re = /a?/,表示a只能重複0次或1次
? = {0,1}
* 前边的内容可以重复任意次以使整个表达式得到匹配。因此,.连在一起就意味着任意数量的不包含换行的字符
* = {0,},即可以不出現,但+是一定要出現一次
| “或”的意思,正則內使用,var re = /a|b/;
() 匹配子項,把正则的整体叫parent,左边第一个小括号里面的正则,叫做这个第一个子项...var re = /(a)(b)(c)/;
[] 用中括号表示,中括号的整体代表一个字符; var str = 'abc',var re = /a[dec]c/;,第1位匹配a,第2位匹配[dec]中的一位,第3位匹配c,則返回true
^ 1、排除 : ^ 如果^写在[]里面的话,就代表排除的意思,如var re = /a1c/;,第2位只要不是bde返回true
2、匹配字符串開頭;如var re= /^d/,開頭必須為數字;
$ $匹配结尾; ^和$的意义就变成了匹配行的开始处和结束处。比如填寫QQ號碼必須為5位-12位, var re = /^d{5,12}$/ {5,12}$表示結束的位置必須是數字
- 如果-写在[]里面的话,就代表范围,范围一定是从小到大的,var re = /a[b-k]c/; [a-z] [0-9] [A-Z]、[a-z0-9A-Z];
var str = 'abc'
var re = /a[a-z]c/
console.log(re.test(str))  //,一共3位,對應上所以是true

//如果str = 'abcd',只會對應前3位,對應不是,所以是false
所以,如果需要多個匹配,+表示[a-z]有多位,可以中間一直匹配,當無法匹配時,再找最後一位匹配

var str = 'abcsdfsdfsdfsdfsdfsdfsf'
var re = re = /a[a-z]+c/ 
console.log(re.test(str))   //true

//所以,過濾html標籤正則是:

var re = /<[^>]+>/g; 
str.replace(re, '');  //應用正則替換為空

</td>
</tr>
<tr>

<td>.</td>
<td>正則中 . 表示任意字符,而匹配真正的點:\.   與一般相反</td>

</tr>

<tr>

<td>\1、 \2、\3</td>
<td>重複的第1、2、3個子項[配合()]; 如/(a)(b)(c)\1/===/(a)(b)(c)a/;表示兩個要完全相同,應用比如匹配p標籤配對</td>

</tr>

</table>

test();

var str = 'abcdef';
var re1 = /b/;
var re2 = /w/;
var re3 = /bc/;
var re4 = /bd/;
alert(re1.test(str)); //true
alert(re2.test(str)); //false
alert(re3.test(str)); //true
alert(re4.test(str)); //false
var str = '473t9487306';
var re = /\D/;
if (re.test(str)) {
  alert('不全是数字');
} else {
  alert('全是数字');
}



search :字符串.search(正则)

var str = 'abcdef';
var re1 = /bcd/;
var re2 = /w/;
var re3 = /B/;
var re4 = /B/i;
var re5 = new RegExp('B', 'i'); //这一行的写法与上面一行的写法,意义完全一样
alert(str.search(re1)); //弹出1 弹的是匹配的首字母的位置
alert(str.search(re2)); //弹出-1
alert(str.search(re3)); //弹出-1 //正则默认下是区分大小写的
alert(str.search(re4)); //弹出1
alert(str.search(re5)); //弹出1



match :返回数组
/d+/g; //这里说明前面的反斜杠d至少出现一次,多则不限

var str = 'sdogh3woiehgxfkjb789paf34dj4pgdfhgdorg43';
var re1 = /\d/;
var re2 = /\d/g;
var re3 = /\d\d/g;
var re4 = /\d\d\d/g;
var re5 = /\d\d\d\d/g;
var re6 = /\d+/g; //这里说明前面的反斜杠d至少出现一次,多则不限
alert(str.match(re1)); //[3] 返回的是找到的第一个数字
alert(str.match(re2)); // [3, 7, 8, 9, 3, 4, 4, 4, 3]
alert(str.match(re3)); //[78, 34, 43]
alert(str.match(re4)); //[789]
alert(str.match(re5)); // null
alert(str.match(re6)); //[3, 789, 34, 4, 43]

replace: 替換所有匹配:

返回替换后的字符串

字符串.replace(正则,想替换的)

例子:敏感词过滤

匹配子项

例子:日期格式化

replace的写法 : 字符串.replace(正则, 新的字符串)

var str1 = 'aaa';
var str2 = 'aaa';
var str3 = 'aaa';
var re1 = /a/;
var re2 = /a/g;
var re3 = /a+/g;
str1 = str1.replace(re1, 'b');
alert(str1); //'baa'
str2 = str2.replace(re2, 'b');
alert(str2); //'bbb'
str3 = str3.replace(re3, 'b');
alert(str3); //'b'            特別留意此處;所有匹配到的都換成b,a+表示匹配多個a,如果匹配到,則替換成b

函数的第一个参数:就是匹配成功的字符,每次匹配到的字符不同,不同長度返回不同*號

aT[1].value = aT[0].value.replace(re, function (str) { //函数的第一个参数:就是匹配成功的字符
  //alert(str);
  var result = '';
  for (var i = 0; i < str.length; i++) {
    result += '*';
  }
  return result;
});

匹配子项

// 匹配子项 : 小括号 () (还有另外一个意思:分组操作)
//把正则的整体叫做(母亲)
// 然后把左边第一个小括号里面的正则,叫做这个第一个子项(母亲的第一个孩子)
// 第二个小括号就是第二个孩子
var str1 = '2013-6-7';
var str2 = '2013-6-7';
var str3 = '2013-6-7';
var str4 = '2013-6-7';
var str5 = '2013-6-7';
var re1 = /\d+-/g;  //+匹配d
var re2 = /\d-+/g; //一个数字加至少一个横杠   +匹配d-
var re3 = /(\d-)+/g;
var re4 = /(\d+)(-)/g;
var re5 = /(\d+)(-)/g;
// str1.replace(re1, function($0){
//  alert($0); //2013- 和 6-
// })
// str2.replace(re2, function($0){
//  alert($0); //3- 和 6-
// })
// str3.replace(re3, function($0){
//  alert($0); //3-6-
// })
/*
        str4.replace(re4, function($0, $1, $2){
            // 第一个参数 : $0 (母亲)       /(\d+)(-)/g;
            // 第二个参数 : $1 (第一个孩子)  (\d+)
            // 第三个参数 : $2 (第二个孩子)  (-)
            // 以此类推
            alert($0); //2013- , 6-
            alert($1); //2013 , 6
            alert($2); // - , -
            //运行一次弹出:2013-, 2013, -, 6-, 6, -
        })
        */
str5 = str5.replace(re5, function ($0, $1, $2) {
  // return $0.substring(0, $0.length - 1) + '.';
  return $1 + '.'; //2013.6.7
})
alert(str5); //2013.6.7

match方法中的匹配子项

var str1 = 'abc';
var re1 = /abc/;
var str2 = 'abc';
var re2 = /(a)(b)(c)/;
var str3 = 'abc';
var re3 = /(a)(b)(c)/g;
alert(str1.match(re1)); //[abc]
alert(str2.match(re2)); //[abc, a, b, c](当match不加g的时候才可以获取到匹配子项的集合)
alert(str3.match(re3)); //[abc] //这里因为re里面加个g,就不会获得上面那一句的结果了

正則表達式字符類

[abc]

例子:o[usb]t——obt、ost、out

字符类 : 一组相似的元素或字符

//字符类 : 用中括号表示,中括号的整体代表一个字符

//字符类 : 一组相似的元素或字符
//字符类 : 用中括号表示,中括号的整体代表一个字符

var str1 = 'abc';
var re1 = /a[bde]c/;
alert(re1.test(str1)); //true
var str2 = 'aec';
var re2 = /a[bde]c/;
alert(re2.test(str2)); //true
var str3 = 'abdc';
var re3 = /a[bde]c/;
alert(re3.test(str3)); //false

//排除 : ^ 如果^写在[]里面的话,就代表排除的意思
var str4 = 'abc';
var re4 = /a[^bde]c/;
alert(re4.test(str4)); //false
var str5 = 'awc';
var re5 = /a[^bde]c/;
alert(re5.test(str5)); //true

//范围 : - 如果-写在[]里面的话,就代表范围,范围一定是从小到大的
var str6 = 'abc';
var re6 = /a[e-j]c/;
alert(re6.test(str6)); //false
var str7 = 'afc';
var re7 = /a[e-j]c/;
alert(re7.test(str7)); //true
var str8 = 'a3c';
var re8 = /a[a-z0-9A-Z]c/;
alert(re8.test(str8)); //true
var str9 = 'a3eJ86Xc';

var re9 = /a[a-z0-9A-Z]+c/; //在中括号外面添加了+,代表可以多位
alert(re9.test(str9)); //true

字符类实例,过滤标签

        var str1 = 'a你c';
        var re1 = /a.c/;

        alert(re1.test(str1)); //true

        var str2 = 'a你c';
        var re2 = /a\.c/;
        alert(re2.test(str2)); //false

        // \b : 独立的部分(起始、结束、空格)
        // \B : 非独立的部分

        var str3 = 'onetwo';
        var re3 = /one/;
        alert(re3.test(str3)); //true;

        var str4 = 'onetwo';
        var re4 = /\bone/; //代表字母o前面必须是独立部分,o前面是起始位置
        alert(re4.test(str4)); //true;

        var str5 = 'onetwo';
        var re5 = /one\b/; //e后面是个t,不是个独立部分
        alert(re5.test(str5)); //false; 

        var str6 = 'one two';
        var re6 = /one\b/; //e后面是个空格,是独立部分
        alert(re6.test(str6)); //true;

        var str7 = 'onetwo';
        var re7 = /\bone\b/; //前面满足后面不满足,整体也就不满足
        alert(re7.test(str7)); //false;

当正则需要传参时,一定要用全称的写法,如var re = new RegExp('\b'+sClass+'\b'),這裏也一定要雙\,字符串當中特殊的字符想輸入,必須再加,如輸出單引號'

var str = 'sddfdsfdsfdsfdsfdddddd'
//先排在一起
var arr = str.split('')
str = arr.sort().join('')
var value = ''
var index = 0;
var re = /(\w)\1+/g;
str.replace(re, function (_0,_1) {
    console.log(_0);
console.log('_1'+_1);
if(index<_0.length){
    index = _0.length;
    value = _1;
}
console.log('最多的字符為:' + value + '出現次數為:' + index);
})

前項聲明,反前項聲明

        var s =  'abacad'
        var re = /a(?=b)/g;    //匹配 ab,但只替換匹配到的ab中的a,b不替換;
        s =  s.replace(re,'*')
        console.log(s);  //*bacad
        var s =  'abacad'
        var re = /a(?!b)/g;    //匹配 ab,a後面不能匹配到b,其他可以匹配
        s =  s.replace(re,'*')
        console.log(s);  //ab*c*d

所以,過濾html標籤,但保留li標籤: re = /<2+>/g;


  1. bde
  2. >?!li

零JS筆記 | Ajax-跨域-百度提示-豆瓣

解決跨域問題:服务器代理或jsonp

1、script標籤;
2、在資料加載進來之前,定義好一個fn,fn接收一個參數,fn裏再拿數據;然後需要時通過script標籤加載對應的遠程文件資源,當遠程文件資源被加載時會執行前面定義好的fn,並且把數據當fn參數傳入;
如:1.txt内容为:

fn([1,2,3])

然后在html开头使用script定义fn,一定要放前面,如放window.onload 里,需使用window.fn(){..}这样调用

function fn(data) {
    alert(data)
}

之后下面window.onload

window.onload = function () {
    var btn = document.getElementById('btn')
    btn.onclick = function () {
        //当按钮点击时再去加载远程资源,让他执行;
        var _script = document.createElement('script')
        _script.src = '1.txt'
        document.body.appendChild(_script)
    }
}
因此,操作别的网站的json数据,主要是能够找到调用的命我空间,即,可以有callback=fn的函数



调用接口实现百度下拉提示:

1)、找到接口,http://suggestion.baidu.com/su?wd=keyword&cb=elmok及调用命名,如elmok即我们可以使用的函数名;

2)、使用实时创建script标签

var _script = document.createElement('script')
_script.src = "http://suggestion.baidu.com/su?wd="+this.value+"&cb=elmok"
document.body.appendChild(_script)

3)、开头创建elmok函数使用数据;

function elmok(data){
    var _ul = document.getElementById('ul1')
    var html =''
    if(data.s.length){  //如果得到数据的长度不为0
        _ul.style.display = 'block'
        for(var i=0;i<data.s.length;i++){
            html+='<li><a target="_blank" href="https://www.baidu.com/s?&wd='+data.s[i]+'">'+data.s[i]+'</a></li>'
        }
        _ul.innerHTML = html;
    }
}

得到的数据如图:
可看到 data.s[i]即为数组,可以循环这个数据输出显示为提示内容;
运行



豆瓣搜索接口:

1)、找到接口callback名:http://api.douban.com/book/subjects?q=keyword&alt=xd&callback=elmok

2)、使用script标签创建

btn.onclick = function () {
    if(_q.value !=''){
        var _script = document.createElement('script')
        _script.src = "http://api.douban.com/book/subjects?q="+_q.value+"&alt=xd&callback=elmok"
        document.body.appendChild(_script)
    }
}

2)、开头创建elmok函数使用数据

function elmok(data){
    var msg = document.getElementById('msg')
    var _list = document.getElementById('list')
    msg.innerHTML = data.title.$t + ':'+data['opensearch:totalResults'].$t
    var _entry = data.entry;
    var html = ''
    for(var i=0;i<_entry.length;i++){
        html+='<dl><dt>'+_entry[i].title.$t+'</dt><dd><img src='+_entry[i].link[2]['@href']+' /></dd>'
    }
    _list.innerHTML = html
}


運行

零JS筆記 | Ajax-留言本

用戶驗證:即時提醒

_username1.onblur = function () {
  ajax('get', 'guestbook/index.php', 'm=index&a=verifyUserName&username=' + this.value, function (data) {
    var d = JSON.parse(data) //數據先轉為objec對像
    verifyUserNameMsg.innerHTML = d.message;
    if (d.code != 0) { //後端定義狀態碼
      verifyUserNameMsg.style.color = 'red'
    } 
    else {
      verifyUserNameMsg.style.color = 'green'
    }
  })
}

用戶註冊:

var password1 = document.getElementById('password1')
var btnReg = document.getElementById('btnReg')
btnReg.onclick = function () {
  ajax('post', 'guestbook/index.php', 'm=index&a=reg&username=' + encodeURI(_username1.value) + '&password=' + password1.value, function (data) {
    var d = JSON.parse(data)
    alert(d.message)
  })
}

更新狀態:

function udpateUserStatus() {
  var uid = getCookie('uid')
  var username = getCookie('username')
  if (uid) {
    _user.style.display = 'block'
    _userinfo.innerHTML = username
    _red.style.display = 'none'
    _login.style.display = 'none'
  } else {
    _user.style.display = 'none'
    _userinfo.innerHTML = username
    _red.style.display = 'block'
    _login.style.display = 'block'
  }
}

//getCookie封裝
function getCookie(key) {
  var arr1 = document.cookie.split('; ')
  for (var i = 0; i < arr1.length; i++) {
    var arr2 = arr1[i].split('=')
    if (arr2[0] == key) {
      return arr2[1]
    }
  }
}

退出:

_logout.onclick = function () {
  ajax('post', 'guestbook/index.php', 'm=index&a=logout', function (data) {
    var d = JSON.parse(data)
    alert(d.message)
    if (!d.code) {
      udpateUserStatus()
    }
  })
  return false
}

發送留言:

btnPost.onclick = function () {
  ajax('post', 'guestbook/index.php', 'm=index&a=send&content=' + encodeURI(content.value), function (data) {
    var d = JSON.parse(data)
    console.log(d);
    if (!d.code) {
      createList(d.data, true)
      udpateUserStatus()
    }
  })
}

顯示留言 :

function showlist() {
  ajax('post', 'guestbook/index.php', 'm=index&a=getList&n=10&page=' + ipage, function (data) {
    var d = JSON.parse(data)
    console.log(d);
    var data = d.data //注意此處判斷;
    if (data) {
      for (var i = 0; i < data.list.length; i++) {
        createList(data.list[i])
      }
    } else {
      if (ipage == 1) {
        _list.innerHTML = '现在还没有留言,快来抢沙发!'
      }
      showMore.style.display = 'none'
    }
  })
}

創建元素添加到頁面:

function createList(data, insert) {
  var dl = document.createElement('dl')
  var dt = document.createElement('dt')
  var strong = document.createElement('strong')
  strong.innerHTML = data.username;
  dt.appendChild(strong)
  var dd1 = document.createElement('dd')
  dd1.innerHTML = data.content
  var dd2 = document.createElement('dd')
  dd2.className = 't'
  var a1 = document.createElement('a')
  a1.href = 'javascript:;'
  a1.innerHTML = '顶(<span>' + data.support + '</span>)'
  var a2 = document.createElement('a')
  a2.href = 'javascript:;'
  a2.innerHTML = '踩(<span>' + data.oppose + '</span>)'
  dd2.appendChild(a2)
  dd2.appendChild(a1)
  dl.appendChild(dt)
  dl.appendChild(dd1)
  dl.appendChild(dd2)
  if (insert && _list.children[0]) {     //如果有第一條,則插入,否則添加;最新總是顯示第一位
    _list.insertBefore(dl, _list.children[0])
  } else {
    _list.appendChild(dl)
  }
}

顯示更多

var showMore = document.getElementById('showMore')
showMore.onclick = function () {
  ipage++
  showlist()
}

comment_ajax.rar

© 2025 J.chongj.chong@qq.com 模板由cho制作.