PDF.js可以实现在html下直接浏览pdf文档,是一款开源的pdf文档读取解析插件,非常强大,能将PDF文件渲染成Canvas。PDF.js主要包含两个库文件,一个pdf.js和一个pdf.worker.js,一个负责API解析,一个负责核心解析。 首先引入pdf.js文件<script type="text/javascript" src=’pdf.js'></script> PDF.js大部分用法都是基于Promise的,PDFJS.getDocument(url)方法返回的就是一个Promise:
1 2 |
PDFJS.getDocument('helloworld.pdf').then(function(pdf) { }); |
PDF的解析工作需要通过pdf.getPage(page)去执行,这个方法返回的也是一个Promise,因此可以去逐页解析PDF:
1 2 |
pdf.getPage(1).then(function(page) { }); |
官网地址:http://mozilla.github.io/pdf.js/ 渲染页面 各PDF页面有它自己的视窗,它定义了像素大小(n.72dpi和初始旋转。默认情况下,该窗口将缩放到PDF但是通过修改视图可以更改此操作。当创建了视图时,还会创建一个初始转换矩阵,它考虑到期望的规模、旋转,并转换坐标系统(0点)PDF文档底部左边,而画布0是 左。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var scale = 1.5; var viewport = page.getViewport(scale); var canvas = document.getElementById('the-canvas'); var context = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; var renderContext = { canvasContext: context, viewport: viewport }; page.render(renderContext); |
1 |
还可以自定义canvas大小: |
1 2 3 4 |
var desiredWidth = 100; var viewport = page.getViewport(1); var scale = desiredWidth / viewport.width; var scaledViewport = page.getViewport(scale); |
官方给出的示例:
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 |
ar url = '//cdn.mozilla.net/pdfjs/helloworld.pdf'; PDFJS.workerSrc = '//mozilla.github.io/pdf.js/build/pdf.worker.js'; var loadingTask = PDFJS.getDocument(url); loadingTask.promise.then(function(pdf) { console.log('PDF loaded'); var pageNumber = 1; pdf.getPage(pageNumber).then(function(page) { console.log('Page loaded'); var scale = 1.5; var viewport = page.getViewport(scale); var canvas = document.getElementById('the-canvas'); var context = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; var renderContext = { canvasContext: context, viewport: viewport }; var renderTask = page.render(renderContext); renderTask.then(function () { console.log('Page rendered'); }); }); }, function (reason) { console.error(reason); }); |
另外较大的PDF文件可以用base 64编码方式加载,例如:
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 |
var pdfData = atob( 'JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog' + 'IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv' + 'TWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0K' + 'Pj4KZW5kb2JqCgozIDAgb2JqCjw8CiAgL1R5cGUgL1BhZ2UKICAvUGFyZW50IDIgMCBSCiAg' + 'L1Jlc291cmNlcyA8PAogICAgL0ZvbnQgPDwKICAgICAgL0YxIDQgMCBSIAogICAgPj4KICA+' + 'PgogIC9Db250ZW50cyA1IDAgUgo+PgplbmRvYmoKCjQgMCBvYmoKPDwKICAvVHlwZSAvRm9u' + 'dAogIC9TdWJ0eXBlIC9UeXBlMQogIC9CYXNlRm9udCAvVGltZXMtUm9tYW4KPj4KZW5kb2Jq' + 'Cgo1IDAgb2JqICAlIHBhZ2UgY29udGVudAo8PAogIC9MZW5ndGggNDQKPj4Kc3RyZWFtCkJU' + 'CjcwIDUwIFRECi9GMSAxMiBUZgooSGVsbG8sIHdvcmxkISkgVGoKRVQKZW5kc3RyZWFtCmVu' + 'ZG9iagoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDEwIDAwMDAwIG4g' + 'CjAwMDAwMDAwNzkgMDAwMDAgbiAKMDAwMDAwMDE3MyAwMDAwMCBuIAowMDAwMDAwMzAxIDAw' + 'MDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9v' + 'dCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G'); PDFJS.workerSrc = '//mozilla.github.io/pdf.js/build/pdf.worker.js'; var loadingTask = PDFJS.getDocument({data: pdfData}); loadingTask.promise.then(function(pdf) { console.log('PDF loaded'); var pageNumber = 1; pdf.getPage(pageNumber).then(function(page) { console.log('Page loaded'); var scale = 1.5; var viewport = page.getViewport(scale); var canvas = document.getElementById('the-canvas'); var context = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; var renderContext = { canvasContext: context, viewport: viewport }; var renderTask = page.render(renderContext); renderTask.then(function () { console.log('Page rendered'); }); }); }, function (reason) { console.error(reason); }); |
pdf翻页处理:
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 |
// If absolute URL from the remote server is provided, configure the CORS // header on that server. var url = '//cdn.mozilla.net/pdfjs/tracemonkey.pdf'; // The workerSrc property shall be specified. PDFJS.workerSrc = '//mozilla.github.io/pdf.js/build/pdf.worker.js'; var pdfDoc = null, pageNum = 1, pageRendering = false, pageNumPending = null, scale = 0.8, canvas = document.getElementById('the-canvas'), ctx = canvas.getContext('2d'); /** * Get page info from document, resize canvas accordingly, and render page. * @param num Page number. */ function renderPage(num) { pageRendering = true; pdfDoc.getPage(num).then(function(page) { var viewport = page.getViewport(scale); canvas.height = viewport.height; canvas.width = viewport.width; var renderContext = { canvasContext: ctx, viewport: viewport }; var renderTask = page.render(renderContext); renderTask.promise.then(function() { pageRendering = false; if (pageNumPending !== null) { renderPage(pageNumPending); pageNumPending = null; } }); }); document.getElementById('page_num').textContent = num; } function queueRenderPage(num) { if (pageRendering) { pageNumPending = num; } else { renderPage(num); } } function onPrevPage() { if (pageNum <= 1) { return; } pageNum--; queueRenderPage(pageNum); } document.getElementById('prev').addEventListener('click', onPrevPage); function onNextPage() { if (pageNum >= pdfDoc.numPages) { return; } pageNum++; queueRenderPage(pageNum); } document.getElementById('next').addEventListener('click', onNextPage); PDFJS.getDocument(url).then(function(pdfDoc_) { pdfDoc = pdfDoc_; document.getElementById('page_count').textContent = pdfDoc.numPages; renderPage(pageNum); }); |
关于page方式的使用: 解析结果,我们可以看下这个对象提供的方法: 方法 返回 getAnnotations A promise that is resolved with an {Array} of the annotation objects. getTextContent That is resolved a TextContent object that represent the page text content. getViewport Contains ‘width’ and ‘height’ properties along with transforms required for rendering. render An object that contains the promise, which is resolved when the page finishes rendering. 我们可以试试调用getTextContent方法,并将其结果打印出来:
1 2 3 |
pdf.getPage(1).then(function(page) { console.log(page); }); |
输入格式大致如下:
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 |
{ "items": [ { "str": "xxx", "dir": "xxx", "width": xxx, "height": xxx, "transform": [ 48, 0, 0, 48, 45.32495, 679.04 ], "fontName": "g_d0_f1" }, { "str": " ", "dir": "ltr", "width": 9.600000000000001, "height": 2304, "transform": [ 48, 0, 0, 48, 285.325, 679.04 ], "fontName": "g_d0_f2" } ], "styles": { "g_d0_f1": { "fontFamily": "monospace", "ascent": 1.05810546875, "descent": -0.26171875, "vertical": false }, "g_d0_f2": { "fontFamily": "sans-serif", "ascent": 0.74365234375, "descent": -0.25634765625 } } } |
PDF.js能将每页文本的字符串、位置、字体都解析出来。 官网用的viewer.js:http://mozilla.github.io/pdf.js/web/viewer.html,首先底图是一个Canvas,内容和PDF一样(通过下面介绍的page.render方法可以得到),底图之上是一个textLayer,这一层就是通过page.getTextContent()得到了字体的位置和样式,再覆盖在Canvas上。 […]
View Detailspackage.josn
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 |
{ "name": "g-ex", "version": "1.0.0", "description": "a gulp template", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "autoprefixer": "^7.1.4", "babel-core": "^6.26.0", "babel-preset-env": "^1.6.0", "gulp": "^3.9.1", "gulp-babel": "^7.0.0", "gulp-clean-css": "^3.9.0", "gulp-concat": "^2.6.1", "gulp-connect": "^5.0.0", "gulp-less": "^3.3.2", "gulp-postcss": "^7.0.0", "gulp-rename": "^1.2.2", "gulp-sourcemaps": "^2.6.1", "gulp-uglify": "^3.0.0", "http-proxy-middleware": "^0.17.4", "uglify-es": "^3.1.3" }, "dependencies": { "gulp-file-include": "^1.2.0" } } |
gulpfile.js
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 |
var gulp = require('gulp'); var connect = require('gulp-connect'); var babel = require('gulp-babel'); var sourcemaps = require('gulp-sourcemaps'); var rename = require('gulp-rename'); var uglify = require('gulp-uglify'); var less = require('gulp-less'); var cleanCss = require('gulp-clean-css'); var autoprefixer = require('autoprefixer'); var postCss = require('gulp-postcss'); var proxy = require('http-proxy-middleware'); var fileinclude = require('gulp-file-include'); // 起服务 gulp.task('connect', function() { connect.server({ root: 'dist', livereload: true, port: 8888, middleware: function(connect, opt) { return [ // proxy('/printbox', { // target: 'http://172.20.8.30:8891', // changeOrigin:true // }), // proxy('/user', { // target: 'http://192.168.0.168:8099/user',//代理的目标地址 // changeOrigin:true,// // pathRewrite:{//路径重写规则 // '^/user':'' // } // }), ] } }); }); // html文件 gulp.task('html', function() { gulp.src('./*.html') .pipe(fileinclude({ prefix: '@@',//变量前缀 @@include basepath: './inc',//引用文件路径 indent:true//保留文件的缩进 })) .pipe(connect.reload()) .pipe(gulp.dest('./dist')); }); // css文件 gulp.task('less', ['html'], function() { gulp.src('./css/*.css') .pipe(connect.reload()) .pipe(gulp.dest('./dist/css')); gulp.src('./css/images/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/css/images')); }); // gulp.task('less', ['html'], function() { // gulp.src('./src/css/*.less') // .pipe(less()) // .pipe(postCss([autoprefixer({browsers: ['last 2 versions']})])) // .pipe(gulp.dest('./dist/css')) // .pipe(cleanCss()) // .pipe(rename({extname: '.min.css'})) // .pipe(connect.reload()) // .pipe(gulp.dest('./dist/css/min')) // }); // js文件 gulp.task('js', function() { gulp.src('./js/*.js') .pipe(connect.reload()) .pipe(gulp.dest('./dist/js')); }); // gulp.task('js',['html'] , function () { // gulp.src('./src/js/*.js') // .pipe(sourcemaps.init()) // .pipe(babel({ // presets: ['env'] // })) // .pipe(gulp.dest('./dist/js')) // .pipe(uglify()) // .pipe(rename({extname: '.min.js'})) // .pipe(sourcemaps.write()) // .pipe(connect.reload()) // .pipe(gulp.dest('./dist/js/min')) // }); // 图片 gulp.task('img', function () { gulp.src('./images/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images')); gulp.src('./images/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images/')); gulp.src('./images/banners/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images/banners')); gulp.src('./images/blog-post/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images/blog-post')); gulp.src('./images/payments/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images/payments')); gulp.src('./images/products/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images/products')); gulp.src('./images/sliders/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images/sliders')); gulp.src('./images/testimonials/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images/testimonials')); }); // fonts gulp.task('font', function(){ gulp.src('./fonts/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/fonts')); }); // 监控 gulp.task('watch', function() { gulp.watch(['./*.html','./inc/*.html'], ['html']); gulp.watch(['./js/*.js'], ['js']); gulp.watch(['./css/*.css'], ['less']); }); // 默认任务 gulp.task('default', ['connect', 'watch', 'js', 'less', 'img', 'font']); |
from:https://www.cnblogs.com/changzhenan/p/8329864.html
View Details闭包 既保证了 内部函数的私有性 又可以向外公开 通过一个已有对象 向它注入属性
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 |
/** * 闭包 * 在函数中定义的函数,在外部使用 * 1、在函数内部定义的函数,在外部不能访问 */ function a(){ /** * b函数是一个私有函数 */ function b(){ alert("aaaa"); } return b; } //var bb = a(); //bb(); (function(){ var aa = 5; function a(){ /** * 公开api */ return { b:b, c:c } } function b(){ alert("b"); } function c(){ alert("c"); } window.a = a; })(); var json = window.a(); json.b(); json.c(); |
from:https://www.cnblogs.com/friends-wf/p/3781859.html
View Details
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 |
/** * 防御型分号 */ ; (function () { //code.... console.log('一开始,我自己执行了!!!'); })(); /** * 形参 -> 实参 * 定义形参->接收实参->最后打印. */ (function (a, b, c) { console.log(a + b + c); })(1, 2, 3) // (function(i){ // console.log(i); // })(window); /** * 声明了不需要返回函数(return) */ void function () { // code.... console.log('不需要返回return!'); }(); |
from:https://www.cnblogs.com/cisum/p/9577246.html
View Details一、什么是闭包和闭包的几种写法和用法 1、什么是闭包 闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。闭包的特点: 1. 作为一个函数变量的一个引用,当函数返回时,其处于激活状态。 2. 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。 简单的说,Javascript允许使用内部函数—即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。 2、闭包的几种写法和用法 首先要明白,在JS中一切都是对象,函数是对象的一种。下面先来看一下闭包的5种写法,简单理解一下什么是闭包。后面会具体解释。
1 2 3 4 5 6 7 8 9 10 11 |
//第1种写法 function Circle(r) { this.r = r; } Circle.PI = 3.14159; Circle.prototype.area = function() { return Circle.PI * this.r * this.r; } var c = new Circle(1.0); alert(c.area()); |
这种写法没什么特别的,只是给函数添加一些属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//第2种写法 var Circle = function() { var obj = new Object(); obj.PI = 3.14159; obj.area = function( r ) { return this.PI * r * r; } return obj; } var c = new Circle(); alert( c.area( 1.0 ) ); |
这种写法是声明一个变量,将一个函数当作值赋给变量。
1 2 3 4 5 6 7 8 |
//第3种写法 var Circle = new Object(); Circle.PI = 3.14159; Circle.Area = function( r ) { return this.PI * r * r; } alert( Circle.Area( 1.0 ) ); |
这种方法最好理解,就是new 一个对象,然后给对象添加属性和方法。
1 2 3 4 5 6 7 8 |
//第4种写法 var Circle={ "PI":3.14159, "area":function(r){ return this.PI * r * r; } }; alert( Circle.area(1.0) ); |
这种方法使用较多,也最为方便。var obj = {}就是声明一个空的对象。
1 2 3 4 |
//第5种写法 var Circle = new Function("this.PI = 3.14159;this.area = function( r ) {return r*r*this.PI;}"); alert( (new Circle()).area(1.0) ); |
说实话,这种写法我是没用过,大家可以参考一下。 总的来说,上面几种方法,第2中和第4中较为常见,大家可以根据习惯选择。 上面代码中出现了JS中常用的Prototype,那么Prototype有什么用呢?下面我们来看一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var dom = function(){ }; dom.Show = function(){ alert("Show Message"); }; dom.prototype.Display = function(){ alert("Property Message"); }; dom.Display(); //error dom.Show(); var d = new dom(); d.Display(); d.Show(); //error |
我们首先声明一个变量,将一个函数赋给他,因为在Javascript中每个函数都有一个Portotype属性,而对象没有。添加两个方法,分别直接添加和添加打破Prototype上面,来看下调用情况。分析结果如下: 1、不使用prototype属性定义的对象方法,是静态方法,只能直接用类名进行调用!另外,此静态方法中无法使用this变量来调用对象其他的属性! 2、使用prototype属性定义的对象方法,是非静态方法,只有在实例化后才能使用!其方法内部可以this来引用对象自身中的其他属性! 下面我们再来看一段代码:
1 2 3 4 5 6 7 8 9 10 |
var dom = function(){ var Name = "Default"; this.Sex = "Boy"; this.success = function(){ alert("Success"); }; }; alert(dom.Name); alert(dom.Sex); |
大家先看看,会显示什么呢? 答案是两个都显示Undefined,为什么呢?这是由于在Javascript中每个function都会形成一个作用域,而这些变量声明在函数中,所以就处于这个函数的作用域中,外部是无法访问的。要想访问变量,就必须new一个实例出来。
1 2 3 4 5 6 7 8 9 |
var html = { Name:'Object', Success:function(){ this.Say = function(){ alert("Hello,world"); }; alert("Obj Success"); } }; |
再来看看这种写法,其实这是Javascript的一个"语法糖",这种写法相当于:
1 2 3 4 5 6 7 |
var html = new Object(); html.Name = 'Object'; html.Success = function(){ this.Say = function(){ alert("Hello,world"); }; alert("Obj Success"); |
变量html是一个对象,不是函数,所以没有Prototype属性,其方法也都是公有方法,html不能被实例化。否则会出现如下错误: 但是他可以作为值赋给其它变量,如var o = html; 我们可以这样使用它:
1 2 |
alert(html.Name); html.Success(); |
说到这里,完了吗?细心的人会问,怎么访问Success方法中的Say方法呢?是html.Success.Say()吗? 当然不是,上面刚说过由于作用域的限制,是访问不到的。所以要用下面的方法访问:
1 2 3 4 5 6 7 8 9 |
var s = new html.Success(); s.Say(); //还可以写到外面 html.Success.prototype.Show = function(){ alert("HaHa"); }; var s = new html.Success(); s.Show(); |
关于Javascript作用域的问题,不是一两句能说清楚的,有兴趣的大家可以网上找些资料看看。 二、Javascript闭包的用途 事实上,通过使用闭包,我们可以做很多事情。比如模拟面向对象的代码风格;更优雅,更简洁的表达出代码;在某些方面提升代码的执行效率。 1、匿名自执行函数 我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处, 比如:别的函数可能误用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的)。 除了每次使用变量都是用var关键字外,我们在实际情况下经常遇到这样一种情况,即有的函数只需要执行一次,其内部变量无需维护, 比如UI的初始化,那么我们可以使用闭包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var data= { table : [], tree : {} }; (function(dm){ for(var i = 0; i < dm.table.rows; i++){ var row = dm.table.rows[i]; for(var j = 0; j < row.cells; i++){ drawCell(i, j); } } })(data); |
我们创建了一个匿名的函数,并立即执行它,由于外部无法引用它内部的变量,因此在函数执行完后会立刻释放资源,关键是不污染全局对象。 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 |
var CachedSearchBox = (function(){ var cache = {}, count = []; return { attachSearchBox : function(dsid){ if(dsid in cache){//如果结果在缓存中 return cache[dsid];//直接返回缓存中的对象 } var fsb = new uikit.webctrl.SearchBox(dsid);//新建 cache[dsid] = fsb;//更新缓存 if(count.length > 100){//保正缓存的大小<=100 delete cache[count.shift()]; } return fsb; }, clearSearchBox : function(dsid){ if(dsid in cache){ cache[dsid].clearSelection(); } } }; })(); CachedSearchBox.attachSearchBox("input"); |
这样我们在第二次调用的时候,就会从缓存中读取到该对象。 3、封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
var person = function(){ //变量作用域为函数内部,外部无法访问 var name = "default"; return { getName : function(){ return name; }, setName : function(newName){ name = newName; } } }(); print(person.name);//直接访问,结果为undefined print(person.getName()); person.setName("abruzzi"); print(person.getName()); 得到结果如下: undefined default abruzzi |
4、实现类和继承
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 |
function Person(){ var name = "default"; return { getName : function(){ return name; }, setName : function(newName){ name = newName; } } }; var p = new Person(); p.setName("Tom"); alert(p.getName()); var Jack = function(){}; //继承自Person Jack.prototype = new Person(); //添加私有方法 Jack.prototype.Say = function(){ alert("Hello,my name is Jack"); }; var j = new Jack(); j.setName("Jack"); j.Say(); alert(j.getName()); |
我们定义了Person,它就像一个类,我们new一个Person对象,访问它的方法。 下面我们定义了Jack,继承Person,并添加自己的方法。 from:https://www.cnblogs.com/jiayc/p/9365837.html
View DetailsChimee是由奇舞团开源的一套H5视频播放器解决方案,由奇舞团视频云前端团队结合在业务和视频编解码方向的沉淀积累倾心打造。Chimee支持MP4、M3U8、FLV等多种媒体格式,同时它也帮我们解决了大部分的兼容性、差异化问题,包括全屏、自动播放、内联播放、直播解码等常见媒体播放需求。 通过便捷的可热插拔的插件开发,能满足业务方快速迭代、灰度发布等要求;让开发者能够更轻松快捷地完成不同业务场景下UI、广告等各种功能需求的开发。 在线演示 免费下载 from:https://www.cnblogs.com/lhb25/p/chimee-h5-video-player.html
View Details
1 2 3 4 5 |
@media screen and (max-width: 300px) { body { background-color:lightblue; } } |
定义和使用 使用 @media 查询,你可以针对不同的媒体类型定义不同的样式。 @media 可以针对不同的屏幕尺寸设置不同的样式,特别是如果你需要设置设计响应式的页面,@media 是非常有用的。 当你重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面。 浏览器支持 表格中的数字表示支持 @media 规则的第一个浏览器的版本号。 Rule Chrome IE FireFox Safari Opera @media 21 9 3.5 4.0 9 CSS 语法 @media mediatype and|not|only (media feature) { CSS-Code; } 你也可以针对不同的媒体使用不同 stylesheets : <link rel="stylesheet" media="mediatype and|not|only (media feature)" href="mystylesheet.css"> 媒体类型 值 描述 all 用于所有设备 aural 已废弃。用于语音和声音合成器 braille 已废弃。 应用于盲文触摸式反馈设备 embossed 已废弃。 用于打印的盲人印刷设备 handheld 已废弃。 用于掌上设备或更小的装置,如PDA和小型电话 print 用于打印机和打印预览 projection 已废弃。 用于投影设备 screen 用于电脑屏幕,平板电脑,智能手机等。 speech 应用于屏幕阅读器等发声设备 tty 已废弃。 用于固定的字符网格,如电报、终端设备和对字符有限制的便携设备 tv 已废弃。 用于电视和网络电视 媒体功能 值 描述 aspect-ratio 定义输出设备中的页面可见区域宽度与高度的比率 color 定义输出设备每一组彩色原件的个数。如果不是彩色设备,则值等于0 color-index 定义在输出设备的彩色查询表中的条目数。如果没有使用彩色查询表,则值等于0 device-aspect-ratio 定义输出设备的屏幕可见宽度与高度的比率。 device-height 定义输出设备的屏幕可见高度。 device-width 定义输出设备的屏幕可见宽度。 grid 用来查询输出设备是否使用栅格或点阵。 height 定义输出设备中的页面可见区域高度。 […]
View Details<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" /> html手机页面 <meta name="viewport" content="width=device-width, initial-scale=1" /> js正则: /<ul.*(?=breadline)(.|\n)*?<\/ul>/gi; 匹配以ul开始 class="breadline"结束外加中间任意内容</ul> ——————— 作者:huang100qi 来源:CSDN 原文:https://blog.csdn.net/huang100qi/article/details/36186573 版权声明:本文为博主原创文章,转载请附上博文链接!
View Details本文主要通过以下几方面来说明懒加载技术的原理,个人前端小菜,有错误请多多指出 一、什么是图片滚动加载? 通俗的讲就是:当访问一个页面的时候,先把img元素或是其他元素的背景图片路径替换成一张大小为1*1px图片的路径(这样就只需请求一次),只有当图片出现在浏览器的可视区域内时,才设置图片正真的路径,让图片显示出来。这就是图片懒加载。 二、为什要使用这个技术? 比如一个页面中有很多图片,如淘宝、京东首页等等,如果一上来就发送这么多请求,页面加载就会很漫长,如果js文件都放在了文档的底部,恰巧页面的头部又依赖这个js文件,那就不好办了。更为要命的是:一上来就发送百八十个请求,服务器可能就吃不消了(又不是只有一两个人在访问这个页面)。 因此优点就很明显了:不仅可以减轻服务器的压力,而且可以让加载好的页面更快地呈现在用户面前(用户体验好)。 三、怎么实现? 关键点如下: 1、页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片(也就没有请求咯,也就提高性能咯),一旦通过javascript设置了图片路径,浏览器才会送请求。有点按需分配的意思,你不想看,就不给你看,你想看了就给你看~ 2、如何获取正真的路径,这个简单,现在正真的路径存在元素的“data-url”(这个名字起个自己认识好记的就行)属性里,要用的时候就取出来,再设置; 3、开始比较之前,先了解一些基本的知识,比如说如何获取某个元素的尺寸大小、滚动条滚动距离及偏移位置距离; 1)屏幕可视窗口大小:对应于图中1、2位置处 原生方法:window.innerHeight 标准浏览器及IE9+ || document.documentElement.clientHeight 标准浏览器及低版本IE标准模式 || document.body.clientHeight 低版本混杂模式 jQuery方法: $(window).height() 2)浏览器窗口顶部与文档顶部之间的距离,也就是滚动条滚动的距离:也就是图中3、4处对应的位置; 原生方法:window.pagYoffset——IE9+及标准浏览器 || document.documentElement.scrollTop 兼容ie低版本的标准模式 || document.body.scrollTop 兼容混杂模式; jQuery方法:$(document).scrollTop(); 3)获取元素的尺寸:对应于图中5、6位置处;左边jquery方法,右边原生方法 $(o).width() = o.style.width; $(o).innerWidth() = o.style.width+o.style.padding; $(o).outerWidth() = o.offsetWidth = o.style.width+o.style.padding+o.style.border; $(o).outerWidth(true) = o.style.width+o.style.padding+o.style.border+o.style.margin; 注意:要使用原生的style.xxx方法获取属性,这个元素必须已经有内嵌的样式,如<div style="…."></div>; 如果原先是通过外部或内部样式表定义css样式,必须使用o.currentStyle[xxx] || document.defaultView.getComputedStyle(0)[xxx]来获取样式值 4)获取元素的位置信息:对应与图中7、8位置处 1)返回元素相对于文档document顶部、左边的距离; jQuery:$(o).offset().top元素距离文档顶的距离,$(o).offset().left元素距离文档左边缘的距离 原生:getoffsetTop(),高程上有具体说明,这边就忽略了; 顺便提一下返回元素相对于第一个以定位的父元素的偏移距离,注意与上面偏移距的区别; jQuery:position()返回一个对象,$(o).position().left = style.left,$(o).position().top = style.top; 4、知道如何获取元素尺寸、偏移距离后,接下来一个问题就是:如何判断某个元素进入或者即将进入可视窗口区域?下面也通过一张图来说明问题。 1)外面最大的框为实际页面的大小,中间浅蓝色的框代表父元素的大小,对象1~8代表元素位于页面上的实际位置;以水平方向来做如下说明! 2)对象8左边界相对于页面左边界的偏移距离(offsetLeft)大于父元素右边界相对于页面左边界的距离,此时可判读元素位于父元素之外; 3)对象7左边界跨过了父元素右边界,此时:对象7左边界相对于页面左边界的偏移距离(offsetLeft)小于 父元素右边界相对于 页面左边界的距离,因此对象7就进入了父元素可视区; 4)在对象6的位置处,对象5的右边界与页面左边界的距离 大于 父元素左边界与页面左边界的距离; 5)在对象5位置处时,对象5的右边界与页面左边界的距离 小于 父元素左边界与页面左边界的距离;此时,可判断元素处于父元素可视区外; 6)因此水平方向必须买足两个条件,才能说明元素位于父元素的可视区内;同理垂直方向也必须满足两个条件;具体见下文的源码; 四、扩展为jquery插件 使用方法:$("selector").scrollLoad({ 参数在代码中有说明 })
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 |
(function($) { $.fn.scrollLoading = function(options) { var defaults = { // 在html标签中存放的属性名称; attr: "data-url", // 父元素默认为window container: window, callback: $.noop }; // 不管有没有传入参数,先合并再说; var params = $.extend({}, defaults, options || {}); // 把父元素转为jquery对象; var container = $(params.container); // 新建一个数组,然后调用each方法,用于存储每个dom对象相关的数据; params.cache = []; $(this).each(function() { // 取出jquery对象中每个dom对象的节点类型,取出每个dom对象上设置的图片路径 var node = this.nodeName.toLowerCase(), url = $(this).attr(params["attr"]); //重组,把每个dom对象上的属性存为一个对象; var data = { obj: $(this), tag: node, url: url }; // 把这个对象加到一个数组中; params.cache.push(data); }); var callback = function(call) { if ($.isFunction(params.callback)) { params.callback.call(call); } }; //每次触发滚动事件时,对每个dom元素与container元素进行位置判断,如果满足条件,就把路径赋予这个dom元素! var loading = function() { // 获取父元素的高度 var contHeight = container.outerHeight(); var contWidth = container.outerWidth(); // 获取父元素相对于文档页顶部的距离,这边要注意了,分为以下两种情况; if (container.get(0) === window) { // 第一种情况父元素为window,获取浏览器滚动条已滚动的距离;$(window)没有offset()方法; var contop = $(window).scrollTop(); var conleft = $(window).scrollLeft(); } else { // 第二种情况父元素为非window元素,获取它的滚动条滚动的距离; var contop = container.offset().top; var conleft = container.offset().left; } $.each(params.cache, function(i, data) { var o = data.obj, tag = data.tag, url = data.url, post, posb, posl, posr; if (o) { //对象顶部与文档顶部之间的距离,如果它小于父元素底部与文档顶部的距离,则说明垂直方向上已经进入可视区域了; post = o.offset().top - (contop + contHeight); //对象底部与文档顶部之间的距离,如果它大于父元素顶部与文档顶部的距离,则说明垂直方向上已经进入可视区域了; posb = o.offset().top + o.height() - contop; // 水平方向上同理; posl = o.offset().left - (conleft + contWidth); posr = o.offset().left + o.width() - conleft; // 只有当这个对象是可视的,并且这四个条件都满足时,才能给这个对象赋予图片路径; if ( o.is(':visible') && (post < 0 && posb > 0) && (posl < 0 && posr > 0) ) { if (url) { //在浏览器窗口内 if (tag === "img") { //设置图片src callback(o.attr("src", url)); } else { // 设置除img之外元素的背景url callback(o.css("background-image", "url("+ url +")")); } } else { // 无地址,直接触发回调 callback(o); } // 给对象设置完图片路径之后,把params.cache中的对象给清除掉;对象再进入可视区,就不再进行重复设置了; data.obj = null; } } }); }; //加载完毕即执行 loading(); //滚动执行 container.bind("scroll", loading); }; })(jQuery); |
五、参考: 1、jQuery.lazyload详解 2、张大大:http://www.zhangxinxu.com/wordpress/?p=1259 3、Jquery图片延迟加载插件jquery.lazyload. http://www.daxueit.com/article/3944.html 4、jQuery.lazyload实现延时加载详解步骤 http://www.daxueit.com/article/21.html 5、jquery lazyload延迟加载技术的实现原理分析 http://www.daxueit.com/article/3777.html 6、Lazyload 延迟加载效果 7、图片延迟加载(lazyload)的实现原理
View Details两端对齐,从概念上来说,其实不难理解。如果不明白什么叫两端对齐,可以玩玩word等办公软件。 下面谈谈如何实现文本的两端对齐。我所知道的大概有以下几种方法 text-align w3school指出,text-align用于设置块级元素内文本的水平对齐方式。如果想使inline元素或inline-block元素居中对齐,可以使用text-align: center方法,对于block元素无法使用text-align实现居中对齐。如果想让block元素居中对齐,可以使用margin: auto方法。 text-align属性下有一个justify值可以设置元素的两端对齐。但是text-align: justify属性有一些不足之处: 在单行文本下,无法实现两端对齐效果。 在多行文本下,无法实现最后一行文本的两端对齐效果。 单行文本
1 2 3 4 5 |
<div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"keith"</span>>unclekeith wanna be a geek!<span class="xml"><span class="hljs-tag"></<span class="hljs-name">div</span>></span></span> .keith { background-color: lightblue; text-align: justify; } |
对于多行文本而言,如下图,按照我们的理解应该如右图显示,可是在设置text-align: justify之后,会按照左图显示。无法是西安最后一行文本的两端对齐效果。 解决方法 如果要真正的实现两端对齐效果,可以用以下方法解决。
1 2 3 4 5 6 7 8 9 |
解决方法的思路:由于在单行文本下和多行文本下最后一样无法实现两端对齐效果,因此给元素新增一行,即可实现<span class="hljs-selector-tag">justify</span>的两个不足之处。 <span class="hljs-selector-class">.keith</span> { <span class="hljs-attribute">text-align</span>: justify; } <span class="hljs-selector-class">.keith</span><span class="hljs-selector-pseudo">:after</span> { <span class="hljs-attribute">display</span>: inline-block; <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>; <span class="hljs-attribute">content</span>: <span class="hljs-string">''</span>; } |
如果感觉最后多了空行,可以为元素设置一个高度,并且设置overflow: hidden隐藏掉即可。 justify-content CSS3新增的flex布局下,有一个justify-content属性,此属性可以控制伸缩项目的水平对齐方式。其中有两个值,可以实现两端对齐。但是justify-content存在兼容性问题,IE10以上,FF,Chrome都支持。而所有浏览器都支持text-align属性
1 2 |
<span class="hljs-attribute">justify-content</span>: space-around。 伸缩项目会平均地分布在伸缩容器内,两端保留一半的空间。 <span class="hljs-attribute">justify-content</span>: space-between。伸缩项目会平均地分布在伸缩容器内,第一个伸缩项目在伸缩容器的左边缘,最后一个伸缩项目在伸缩容器的右边缘。 |
justify-content: space-around; justify-content: space-between text-justify 还有一个text-justify属性,这个属性估计很少人会使用到,因为只有IE浏览器和FF55以上的浏览器才支持。因为兼容性实在不好,就不说了.. from:https://www.cnblogs.com/unclekeith/p/7073536.html
View Details