webkit-box

【注:本文所有的代码和实例仅在chrome和safari等webkit内核的浏览器测试通过】

如果说从web Pages 能够转到web app时代,那么css3和html5其他相关技术一定是巨大的功臣。

唯一的遗憾就是pc端浏览器的泛滥导致了我们不得不走所谓的优雅降级,而且这种降级是降到新技术几乎木有多大的用武之地。
于是,客户端还算统一的移动端开始成了一个大的试验田。能够让众人大肆的在上面舒展拳脚。诸如众多新起的ui库或者框架(jquery-mobile, sencha, phoneGap ...),可见在移动终端上确实还有不小的田地。纵使如此,效率仍旧成为一个最大的瓶颈。

之前有一种尝试是用CSS3的transfrom或者animation给一个duration和ease的属性来做动画,这样不管改变任何style样式,都会根据这个ease有缓动的效果。
例如:

/* webkit */-webkit-transition-duration: 500ms;

在webkit内核浏览器下,只要有这个属性,再去改变这个元素任何的样式,它都会以一个默认的缓动效果完成。

+ ?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

/**

 * CSS3 animation by transform

 * @example

 * Let(el)

 *      .to(500, 200)

 *      .rotate(180)

 *      .scale(.5)

 *      .set({

 *          background-color: ‘red‘,

 *          border-color: ‘green‘

 *      })

 *      .duration(2000)

 *      .skew(50, -10)

 *      .then()

 *          .set(‘opacity‘, .5)

 *          .duration(‘1s‘)

 *          .scale(1)

 *          .pop()

 *      .end();

 */

(function (win, undefined) {

    

    var initializing = false,

        superTest = /horizon/.test(function () {horizon;}) ? /\b_super\b/ : /.*/;

    // 临时Class

    this.Class = function () {};

    // 继承方法extend

    Class.extend = function (prop) {

        var _super = this.prototype;

        //创建一个实例,但不执行init

        initializing = true;

        var prototype = new this();

        initializing = false;

        for (var name in prop) {

            // 用闭包保证多级继承不会污染

            prototype[name] = (typeof prop[name] === ‘function‘ && typeof _super[name] === ‘function‘ && superTest.test(prop[name])) ? (function (name, fn) {

                    return function () {

                        var temp = this._super;

                        // 当前子类通过_super继承父类

                        this._super = _super[name];

                        //继承方法执行完毕后还原

                        var ret = fn.apply(this, arguments);

                        this._super = temp;

                        return ret;

                    }

                })(name, prop[name]) : prop[name];

        }

        

        //真实的constructor

        function Class () {

            if (!initializing && this.init) {

                this.init.apply(this, arguments);

            }

        }

        Class.prototype = prototype;

        Class.constructor = Class;

        Class.extend = arguments.callee;

        return Class;

    }

    

    // 样式为数字+px 的属性

    var map = {

        ‘top‘: ‘px‘,

        ‘left‘: ‘px‘,

        ‘right‘: ‘px‘,

        ‘bottom‘: ‘px‘,

        ‘width‘: ‘px‘,

        ‘height‘: ‘px‘,

        ‘font-size‘: ‘px‘,

        ‘margin‘: ‘px‘,

        ‘margin-top‘: ‘px‘,

        ‘margin-left‘: ‘px‘,

        ‘margin-right‘: ‘px‘,

        ‘margin-bottom‘: ‘px‘,

        ‘padding‘: ‘px‘,

        ‘padding-left‘: ‘px‘,

        ‘padding-right‘: ‘px‘,

        ‘padding-top‘: ‘px‘,

        ‘padding-bottom‘: ‘px‘,

        ‘border-width‘: ‘px‘

    };

    /**

     * Let package

     */

    var Let = function (selector) {

        var el = Let.G(selector);

        return new Anim(el);

    };

    Let.defaults = {

        duration: 500

    };

    Let.ease = {

        ‘in‘ : ‘ease-in‘,

        ‘out‘: ‘ease-out‘,

        ‘in-out‘: ‘ease-in-out‘,

        ‘snap‘ : ‘cubic-bezier(0,1,.5,1)‘

    };

    Let.G = function (selector) {

        if (typeof selector != ‘string‘ && selector.nodeType == 1) {

            return selector;

        }

        return document.getElementById(selector) || document.querySelectorAll(selector)[0];    

    };

    /**

     * EventEmitter

     * {Class}

     */

    var EventEmitter = Class.extend({

        init: function () {

            this.callbacks = {};

        },     

        on: function (event, fn) {

            (this.callbacks[event] = this.callbacks[event] || []).push(fn);

            return this;

        },

        /**

         * param {event} 指定event

         * params 指定event的callback的参数

         */

        fire: function (event) {

            var args = Array.prototype.slice.call(arguments, 1),

                callbacks = this.callbacks[event],

                len;

            if (callbacks) {

                for (var i = 0, len = callbacks.length; i < len; i ++) {

                    callbacks[i].apply(this, args);

                }

            }

            return this;

        }

                

    });

    /**

     * Anim

     * {Class}

     * @inherit from EventEmitter

     */

    var Anim = EventEmitter.extend({

        init: function (el) {

            this._super();

            if (!(this instanceof Anim)) {

                return new Anim(el);

            }

            this.el = el;

            this._props = {};

            this._rotate = 0;

            this._transitionProps = [];

            this._transforms = [];

            this.duration(Let.defaults.duration);

            

        },

        transform : function (transform) {

            this._transforms.push(transform);

            return this;

        },

        // skew methods

        skew: function (x, y) {

            y = y || 0;

            return this.transform(‘skew(‘+ x +‘deg, ‘+ y +‘deg)‘);

        },

        skewX: function (x) {

            return this.transform(‘skewX(‘+ x +‘deg)‘);   

        },

        skewY: function (y) {

            return this.transform(‘skewY(‘+ y +‘deg)‘);   

        },

        // translate methods

        translate: function (x, y) {

            y = y || 0;

            return this.transform(‘translate(‘+ x +‘px, ‘+ y +‘px)‘);

        },

        to: function (x, y) {

            return this.translate(x, y);   

        },

        translateX: function (x) {

            return this.transform(‘translateX(‘+ x +‘px)‘);        

        },

        x: function (x) {

            return this.translateX(x);  

        },

        translateY: function (y) {

            return this.transform(‘translateY(‘+ y +‘px)‘);        

        },

        y: function (y) {

            return this.translateY(y);  

        },

        // scale methods

        scale: function (x, y) {

            y = (y == null) ? x : y;

            return this.transform(‘scale(‘+ x +‘, ‘+ y +‘)‘);

        },

        scaleX: function (x) {

            return this.transform(‘scaleX(‘+ x +‘)‘);

        },

        scaleY: function (y) {

            return this.transform(‘scaleY(‘+ y +‘)‘);

        },

        // rotate methods

        rotate: function (n) {

            return this.transform(‘rotate(‘+ n +‘deg)‘);

        },

        // set transition ease

        ease: function (fn) {

            fn = Let.ease[fn] || fn || ‘ease‘;

            return this.setVendorProperty(‘transition-timing-function‘, fn);

        },

        //set duration time

        duration: function (n) {

            n = this._duration = (typeof n == ‘string‘) ? parseFloat(n)*1000 : n;

            return this.setVendorProperty(‘transition-duration‘, n + ‘ms‘);

        },

        // set delay time

        delay: function (n) {

            n = (typeof n == ‘string‘) ? parseFloat(n) * 1000 : n;

            return this.setVendorProperty(‘transition-delay‘, n + ‘ms‘);

        },

        // set property to val

        setProperty: function (prop, val) {

            this._props[prop] = val;

            return this;

        },

        setVendorProperty: function (prop, val) {

            this.setProperty(‘-webkit-‘ + prop, val);

            this.setProperty(‘-moz-‘ + prop, val);

            this.setProperty(‘-ms-‘ + prop, val);

            this.setProperty(‘-o-‘ + prop, val);

            return this;

        },

        set: function (prop, val) {

            var _store = {};

            if (typeof prop == ‘string‘ && val != undefined) {

                _store[prop] = val;

            } else if (typeof prop == ‘object‘ && prop.constructor.prototype.hasOwnProperty(‘hasOwnProperty‘)) {

                _store = prop;

            }

            

            for (var key in _store) {

                this.transition(key);

                if (typeof _store[key] == ‘number‘ && map[key]) {

                    _store[key] += map[key];

                }

                this._props[key] = _store[key];

            }

            return this;

        },

        

        // add value to a property

        add: function (prop, val) {

            var self = this;

            return this.on(‘start‘, function () {

                var curr = parseInt(self.current(prop), 10);

                self.set(prop, curr + val + ‘px‘);

            })

        },

        // sub value to a property

        sub: function (prop, val) {

            var self = this;

            return this.on(‘start‘, function () {

                var curr = parseInt(self.current(prop), 10);

                self.set(prop, curr - val + ‘px‘);

            })

        },

        current: function (prop) {

            return !!window.getComputedStyle ? document.defaultView.getComputedStyle(this.el, null).getPropertyValue(prop) : this.el.currentStyle(prop);

        },

        transition: function (prop) {

            for (var i = 0; i < this._transitionProps.length; i ++) {

                if (this._transitionProps[i] == prop) {

                    return this;

                }

            }

            this._transitionProps.push(prop);

            return this;

        },

        applyPropertys: function () {

            var props = this._props,

                el = this.el;

            for (var prop in props) {

                if (props.hasOwnProperty(prop)) {

                    el.style.setProperty ? el.style.setProperty(prop, props[prop], ‘‘) : el.style[prop] = props[prop];

                }

            }

            return this;

        },

        

        // then

        then: function (fn) {

            if (fn instanceof Anim) {

                this.on(‘end‘, function () {

                    fn.end();      

                })

            } else if (typeof fn == ‘function‘) {

                this.on(‘end‘, fn);

            } else {

                var clone = new Anim(this.el);

                clone._transforms = this._transforms.slice(0);

                this.then(clone);

                clone.parent = this;

                return clone;

            }

            return this;

        },

        pop: function () {

            return this.parent; 

        },

        end: function (fn) {

            var self = this;

            this.fire(‘start‘);

            if (this._transforms.length > 0) {

                this.setVendorProperty(‘transform‘, this._transforms.join(‘ ‘));

            }

            this.setVendorProperty(‘transition-properties‘, this._transitionProps.join(‘, ‘));

            this.applyPropertys();

            if (fn) { this.then(fn) }

            setTimeout(function () {

                self.fire(‘end‘);      

            }, this._duration);

            return this;

        }

        

    });

    this.Let = win.Let = Let;

    

 })(window)

比如下面代码:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

<div id="test"></div>

<script>

Let(‘#test‘)

    .to(200, 200)

    .rotate(1000)

    .scale(.5)

    .set({

        ‘background-color‘: ‘red‘,

        ‘width‘: 300

    })

    .duration(2000)

    .then()

        .set(‘opacity‘, .5)

        .set(‘height‘, 200)

        .duration(‘1s‘)

        .scale(1.5)

        .to(300, 300)

        .pop()

    .end()

    

</script>

<!DOCTYPE html><html><head><script src="http://hongru.github.com/resource/css3-transform/let.js" ></script><style>
#test {
width: 100px;
height: 100px;
background: #000;
}
</style></head><body><div id="test"><br /></div><script >
Let(‘#test‘)
.to(200, 200)
.rotate(1000)
.scale(.5)
.set({
‘background-color‘: ‘red‘,
‘width‘: 300
})
.duration(2000)
.then()
.set(‘opacity‘, .5)
.set(‘height‘, 200)
.duration(‘1s‘)
.scale(1.5)
.to(300, 300)
.pop()
.end()

</script></body></html>

这样子有好处是可以针对所有的style样式。所以可以用同样的方式来对 left, top,margin-left,margin-top 之类的css2 的style属性来完成dom的相应变化。

但是,其实,用transform或者animation来操作css2的style属性。效率依然不高。在当前的移动终端,ipad还ok(毕竟是乔帮主的产品),iphone和android pad上执行效率在大部分情况下很难达到优秀app所要求的体验。

所以要做滑动之类的改变dom位置的体验。更好的实现应该是用纯粹的translate来改变位置,为了更好的与之配合,布局就尤为重要。

下面看看webkit提供的 display:-webkit-box; 亦即

Flexible Box Module

我称其为【流体盒模型】
W3C草案(http://www.w3.org/TR/css3-flexbox/)的描述 如下:

 a CSS box model optimized for interface design. It provides an additional layout system alongside the ones already in CSS. [CSS21] In this new box model, the children of a box are laid out either horizontally or vertically, and unused space can be assigned to a particular child or distributed among the children by assignment of “flex” to the children that should expand. Nesting of these boxes (horizontal inside vertical, or vertical inside horizontal) can be used to build layouts in two dimensions. This model is based on the box model in the XUL user-interface language used for the user interface of many Mozilla-based applications (such as Firefox).

偶英文蹩脚,就不翻译了,用另外一番话来看它的意思:

1.之前要实现横列的web布局,通常就是float或者display:inline-block; 但是都不能做到真正的流体布局。至少width要自己去算百分比。
2.flexible box 就可以实现真正意义上的流体布局。只要给出相应属性,浏览器会帮我们做额外的计算。

提供的关于盒模型的几个属性:

?

box-orient           子元素排列 vertical or horizontal

box-flex             兄弟元素之间比例,仅作一个系数

box-align            box 排列

box-direction        box 方向

box-flex-group       以组为单位的流体系数

box-lines           

box-ordinal-group    以组为单位的子元素排列方向

box-pack

以下是关于flexible box的几个实例
三列自适应布局,且有固定margin

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

<!DOCTYPE html>

<html>

<style>

.wrap {

    display: -webkit-box;

    -webkit-box-orient: horizontal;

}

.child {

    min-height: 200px;

    border: 2px solid #666;

    -webkit-box-flex: 1;

    margin: 10px;

    font-size: 100px;

    font-weight: bold;

    font-family: Georgia;

    -webkit-box-align: center;

}

</style>

<div class="wrap">

<div class="child">1</div>

<div class="child">2</div>

<div class="child">3</div>

</div>

</html>

<!DOCTYPE html><html><style>
.wrap {
display: -webkit-box;
-webkit-box-orient: horizontal;
}
.child {
min-height: 200px;
border: 2px solid #666;
-webkit-box-flex: 1;
margin: 10px;
font-size: 100px;
font-weight: bold;
font-family: Georgia;
-webkit-box-align: center;
}
</style><div class="wrap"><div class="child">1</div><div class="child">2</div><div class="child">3</div></div></html>

当一列定宽,其余两列分配不同比例亦可(三列布局,一列定宽,其余两列按1:2的比例自适应)

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

<!DOCTYPE html>

<html>

<meta charset="utf-8" />

<style>

.wrap {

    display: -webkit-box;

    -webkit-box-orient: horizontal;

}

.child {

    min-height: 200px;

    border: 2px solid #666;

    margin: 10px;

    font-size: 40px;

    font-weight: bold;

    font-family: Georgia;

    -webkit-box-align: center;

}

.w200 {width: 200px}

.flex1 {-webkit-box-flex: 1}

.flex2 {-webkit-box-flex: 2}

</style>

<div class="wrap">

<div class="child w200">200px</div>

<div class="child flex1">比例1</div>

<div class="child flex2">比例2</div>

</div>

</html>

<!DOCTYPE html><html><meta charset="utf-8" /><style>
.wrap {
display: -webkit-box;
-webkit-box-orient: horizontal;
}
.child {
min-height: 200px;
border: 2px solid #666;
margin: 10px;
font-size: 40px;
font-weight: bold;
font-family: Georgia;
-webkit-box-align: center;
}
.w200 {width: 200px}
.flex1 {-webkit-box-flex: 1}
.flex2 {-webkit-box-flex: 2}
</style><div class="wrap"><div class="child w200">200px</div><div class="child flex1">比例1</div><div class="child flex2">比例2</div></div></html>
  

下面是一个常见的web page 的基本布局

?

<style>

header, footer, section {

    border: 10px solid #333;

    font-family: Georgia;

    font-size: 40px;

    text-align: center;

    margin: 10px;

}

#doc {

    width: 80%;

    min-width: 600px;

    height: 100%;

    display: -webkit-box;

    -webkit-box-orient: vertical;

    margin: 0 auto;

}

header,

footer {

    min-height: 100px;

    -webkit-box-flex: 1;

}

#content {

    min-height: 400px;

    display: -webkit-box;

    -webkit-box-orient: horizontal;

}

.w200 {width: 200px}

.flex1 {-webkit-box-flex: 1}

.flex2 {-webkit-box-flex: 2}

.flex3 {-webkit-box-flex: 3}

</style>

<div id="doc">

    <header>Header</header>

    <div id="content">

        <section class="w200">定宽200</section>

        <section class="flex3">比例3</section>

        <section class="flex1">比例1</section>

    </div>

    <footer>Footer</footer>

</div>

 <!DOCTYPE html><html><meta charset="utf-8" /><style>
header, footer, section {
border: 10px solid #333;
font-family: Georgia;
font-size: 40px;
text-align: center;
margin: 10px;
}
#doc {
width: 80%;
min-width: 600px;
height: 100%;
display: -webkit-box;
-webkit-box-orient: vertical;
margin: 0 auto;
}
header,
footer {
min-height: 100px;
-webkit-box-flex: 1;
}
#content {
min-height: 400px;
display: -webkit-box;
-webkit-box-orient: horizontal;
}

.w200 {width: 200px}
.flex1 {-webkit-box-flex: 1}
.flex2 {-webkit-box-flex: 2}
.flex3 {-webkit-box-flex: 3}
</style><div id="doc"><header>Header</header><div id="content"><section class="w200">定宽200</section><section class="flex3">比例3</section><section class="flex1">比例1</section></div><footer>Footer</footer></div></html>
 

有了 flexible box 后,横列布局的时候不用计算外围容器和容器里面的元素的宽度。然后再进行横向的滑动的效果就会省去不少麻烦。

+ ?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

/**

 * css3 translate flip

 * -webkit-box

 * @author: horizon

 */

(function (win, undefined) {

 

    var initializing = false,

        superTest = /horizon/.test(function () {horizon;}) ? /\b_super\b/ : /.*/;

    this.Class = function () {};

    Class.extend = function (prop) {

        var _super = this.prototype;

        initializing = true;

        var prototype = new this();

        initializing = false;

        for (var name in prop) {

            prototype[name] = (typeof prop[name] === ‘function‘ && typeof _super[name] === ‘function‘ && superTest.test(prop[name])) ? (function (name, fn) {

                    return function () {

                        var temp = this._super;

                        this._super = _super[name];

                        var ret = fn.apply(this, arguments);

                        this._super = temp;

                        return ret;

                    }

                })(name, prop[name]) : prop[name];

        }

        

        function Class () {

            if (!initializing && this.init) {

                this.init.apply(this, arguments);

            }

        }

        Class.prototype = prototype;

        Class.constructor = Class;

        Class.extend = arguments.callee;

        return Class;

    };

    var $support = {

        transform3d: (‘WebKitCSSMatrix‘ in win),

        touch: (‘ontouchstart‘ in win)

    };

    var $E = {

        start: $support.touch ? ‘touchstart‘ : ‘mousedown‘,

        move: $support.touch ? ‘touchmove‘ : ‘mousemove‘,

        end: $support.touch ? ‘touchend‘ : ‘mouseup‘

    };

    function getTranslate (x) {

        return $support.transform3d ? ‘translate3d(‘+x+‘px, 0, 0)‘ : ‘translate(‘+x+‘px, 0)‘;

    }

    function getPage (event, page) {

        return $support.touch ? event.changedTouches[0][page] : event[page];

    }

    var Css3Flip = Class.extend({

        init: function (selector, conf) {

            var self = this;

            

            if (selector.nodeType && selector.nodeType == 1) {

                self.element = selector;

            } else if (typeof selector == ‘string‘) {

                self.element = document.getElementById(selector) || document.querySelector(selector);

            }

            

            self.element.style.display = ‘-webkit-box‘;

            self.element.style.webkitTransitionProperty = ‘-webkit-transform‘;

            self.element.style.webkitTransitionTimingFunction = ‘cubic-bezier(0,0,0.25,1)‘;

            self.element.style.webkitTransitionDuration = ‘0‘;

            self.element.style.webkitTransform = getTranslate(0);

            self.conf = conf || {};

            self.touchEnabled = true;

            self.currentPoint = 0;

            self.currentX = 0;

            self.refresh();

            

            // 支持handleEvent

            self.element.addEventListener($E.start, self, false);

            self.element.addEventListener($E.move, self, false);

            document.addEventListener($E.end, self, false);

            return self;

            

        },

        handleEvent: function(event) {

            var self = this;

            switch (event.type) {

                case $E.start:

                    self._touchStart(event);

                    break;

                case $E.move:

                    self._touchMove(event);

                    break;

                case $E.end:

                    self._touchEnd(event);

                    break;

                case ‘click‘:

                    self._click(event);

                    break;

            }

        },

        refresh: function() {

            var self = this;

            var conf = self.conf;

            // setting max point

            self.maxPoint = conf.point || (function() {

                var childNodes = self.element.childNodes,

                    itemLength = 0,

                    i = 0,

                    len = childNodes.length,

                    node;

                for(; i < len; i++) {

                    node = childNodes[i];

                    if (node.nodeType === 1) {

                        itemLength++;

                    }

                }

                if (itemLength > 0) {

                    itemLength--;

                }

    

                return itemLength;

            })();

            // setting distance

            self.distance = conf.distance || self.element.scrollWidth / (self.maxPoint + 1);

            // setting maxX

            self.maxX = conf.maxX ? - conf.maxX : - self.distance * self.maxPoint;

    

            self.moveToPoint(self.currentPoint);

        },

        hasNext: function() {

            var self = this;

    

            return self.currentPoint < self.maxPoint;

        },

        hasPrev: function() {

            var self = this;

    

            return self.currentPoint > 0;

        },

        toNext: function() {

            var self = this;

            if (!self.hasNext()) {

                return;

            }

            self.moveToPoint(self.currentPoint + 1);

        },

        toPrev: function() {

            var self = this;

            if (!self.hasPrev()) {

                return;

            }

            self.moveToPoint(self.currentPoint - 1);

        },

        moveToPoint: function(point) {

            var self = this;

            self.currentPoint =

                (point < 0) ? 0 :

                (point > self.maxPoint) ? self.maxPoint :

                parseInt(point);

            self.element.style.webkitTransitionDuration = ‘500ms‘;

            self._setX(- self.currentPoint * self.distance)

            var ev = document.createEvent(‘Event‘);

            ev.initEvent(‘css3flip.moveend‘, true, false);

            self.element.dispatchEvent(ev);

        },

        _setX: function(x) {

            var self = this;

            self.currentX = x;

            self.element.style.webkitTransform = getTranslate(x);

        },

        _touchStart: function(event) {

            var self = this;

            if (!self.touchEnabled) {

                return;

            }

            if (!$support.touch) {

                event.preventDefault();

            }

            self.element.style.webkitTransitionDuration = ‘0‘;

            self.scrolling = true;

            self.moveReady = false;

            self.startPageX = getPage(event, ‘pageX‘);

            self.startPageY = getPage(event, ‘pageY‘);

            self.basePageX = self.startPageX;

            self.directionX = 0;

            self.startTime = event.timeStamp;

        },

        _touchMove: function(event) {

            var self = this;

            if (!self.scrolling) {

                return;

            }

            var pageX = getPage(event, ‘pageX‘),

                pageY = getPage(event, ‘pageY‘),

                distX,

                newX,

                deltaX,

                deltaY;

            if (self.moveReady) {

                event.preventDefault();

                event.stopPropagation();

                distX = pageX - self.basePageX;

                newX = self.currentX + distX;

                if (newX >= 0 || newX < self.maxX) {

                    newX = Math.round(self.currentX + distX / 3);

                }

                self._setX(newX);

                self.directionX = distX > 0 ? -1 : 1;

            }

            else {

                deltaX = Math.abs(pageX - self.startPageX);

                deltaY = Math.abs(pageY - self.startPageY);

                if (deltaX > 5) {

                    event.preventDefault();

                    event.stopPropagation();

                    self.moveReady = true;

                    self.element.addEventListener(‘click‘, self, true);

                }

                else if (deltaY > 5) {

                    self.scrolling = false;

                }

            }

            self.basePageX = pageX;

        },

        _touchEnd: function(event) {

            var self = this;

            if (!self.scrolling) {

                return;

            }

            self.scrolling = false;

            var newPoint = -self.currentX / self.distance;

            newPoint =

                (self.directionX > 0) ? Math.ceil(newPoint) :

                (self.directionX < 0) ? Math.floor(newPoint) :

                Math.round(newPoint);

            self.moveToPoint(newPoint);

            setTimeout(function() {

                self.element.removeEventListener(‘click‘, self, true);

            }, 200);

        },

        _click: function(event) {

            var self = this;

            event.stopPropagation();

            event.preventDefault();

        },

        destroy: function() {

            var self = this;

            self.element.removeEventListener(touchStartEvent, self);

            self.element.removeEventListener(touchMoveEvent, self);

            document.removeEventListener(touchEndEvent, self);

        }

        

        

    });

    this.Css3Flip = function (selector, conf) {

        return (this instanceof Css3Flip) ? this.init(selector, conf) : new Css3Flip(selector, conf);

    }

    

 

 })(window);

<!DOCTYPE html><html><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width" /><style>
#doc {
width: 800px;
overflow: hidden;
margin: 0 auto;
}
section {
border: 10px solid #333;
font-size: 100px;
text-align: center;
width: 700px;
margin: 0 40px;
min-height: 600px;
}
#wrap {
display: -webkit-box;
cursor: move;
}
</style></head><body><div id="doc"><div id="wrap"><section>1</section><section>2</section><section>3</section><section>4</section></div></div><script src="http://hongru.github.com/resource/touchflip/flip.js" ></script><script>
Css3Flip("#wrap");
</script></body></html>

  

通过改变translate 而不是改变 left 或者margin-left 来实现滑动,效率提升会很明显,平滑度几乎可以媲美native app。在对js执行效率不是很高的移动终端中尤为明显。

时间: 2024-11-06 16:25:07

webkit-box的相关文章

Webkit Box 模型属性备忘

-webkit-box-orient: horizontal||vertical 设置或检索弹性盒模型对象的子元素的排列方式.对应的脚本特性为boxOrient.需设置容器的display:-webkit-box; CSS样式: html,body,div{ margin:0px; padding:0px;} .orient{display:-webkit-box;-webkit-box-orient:horizontal; width:600px; margin:0 auto;} .orien

CSS3 学习小结

写样式时有时遇到浏览器兼容问题:-webkit-transition:chrome和safari-moz-transition:firefox-ms-transition:IE-o-transition:Opera但是在JS 中则不允许带前边的横杠,并且首字母大写,如WebkitTransition,MozTransition,MsTransition,OTransition属性选择器:设置样式的格式:表签名[属性名=value]{}表签名[属性名~=value]{}//属性值是一个词组用空格分

关于JS实现延迟加载

不多说 直接上代码 <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> *{ margin: 0px; padding: 0px; - webkit - box - sizing: border - box; - moz - box - sizin

关于display: box 和 box-flex

这两天做手机项目,使用到这个css3新属性.现在还不为所有浏览器支持,所以使用的时候要加上前缀.使用方法见下面: html代码: <div class="s-indLine">             <div class="s-indNav s-indIntro">                 <span class="s-icon"></span>                 <p

浏览苹果自己的WebKit项目SVN代码库最近的ChangeLog

https://trac.webkit.org/export/178624/trunk/Source/WebCore/ChangeLog 2015-01-15 Antti Koivisto Rename Font to FontCascade https://bugs.webkit.org/show_bug.cgi?id=140442 2015-01-11 Sam Weinig Remove support for SharedWorkers https://bugs.webkit.org/sh

Webkit二:RenderTree 创建

RenderObject 作为所有Render 树节点的基类,完全类似与DOM树中的Node基类,它是构成Render 树的基础,作用非比寻常,其中包含了构成Render 树所可能涉及到的一些基本属性及方法,内容相当多,其主要数据成员及方法分别如下: 其中成员m_parent.m_previous.m_next为构建Render 树设置好关联基础:m_Node 则为DOM 树中对应的节点:m_style 成员则描述该节点对应的各种CSS基本属性数据,下面会单独介绍:至于其他的诸如m_positi

CSS3与页面布局学习总结(二)——Box Model、边距折叠、内联与块标签、CSSReset

一.盒子模型(Box Model) 盒子模型也有人称为框模型,HTML中的多数元素都会在浏览器中生成一个矩形的区域,每个区域包含四个组成部分,从外向内依次是:外边距(Margin).边框(Border).内边距(Padding)和内容(Content),其实盒子模型有两种,分别是 ie 盒子模型和标准 w3c 盒子模型,加上了doctype声明,让所有浏览器都会采用标准 w3c 盒子模型去解释你的盒子.当设置一个元素的样式如下: <!DOCTYPE html> <html> <

CSS盒子模型之CSS3可伸缩框属性(Flexible Box)

CSS盒子模型(下) 一.CSS3可伸缩框(Flexible Box) 可伸缩框属性(Flexible Box)是css3新添加的盒子模型属性,有人称之为弹性盒模型,它的出现打破了我们经常使用的浮动布局,实现垂直等高.水平均分.按比例划分等分布方式以及如何处理可用的空间.使该模型,可以很轻松的创建自适应浏览器窗口的流动布局或自适应字体大小的弹性布局.但是它有一定的局限性,在firefox.chrome这浏览器下需要使用它们的私有属性来定义:firefox(-moz).chrome(-webkit

.NET多种WebKit内核/Blink内核浏览器

转自:http://www.wuleba.com/23590.html[吾乐吧软件站] 星级 名称语言版本优点缺点 ★★ Chromium Embedded Framework (CEF) C/C++ 3.1547.1406 1.开源项目,有社区支持 1.C++更新维护成本太高 2.一直都还在更新维护 2.开发难度较大 3.基于CEF二次开发项目多 ★★★★ Xilium.CefGlue C# 3.1547.1448 1.基于CEF,DotNET封装 1.参考资料较少 2.继承CEF优良特性 2

CSS3 display:flex和display:box有什么区别?

**区别**,仅是各阶段草案命名.- W3C 2009年第1次草案:[display:box;](https://www.w3.org/TR/2009/WD-css3-flexbox-20090723/)- W3C 2011年第2次草案:[display:flexbox | inline-flexbox;](https://www.w3.org/TR/2011/WD-css3-flexbox-20110322/)- W3C 2012年第5次草案及以后的候选推荐标准:[display:flex |