Prechádzať zdrojové kódy

完善网页截屏工具

[email protected] 2 rokov pred
rodič
commit
fe318e9e6d

+ 13 - 88
apps/background/background.js

@@ -215,6 +215,7 @@ let BgPageInstance = (function () {
         }
     };
 
+
     // 捕获当前页面可视区域
     let _captureVisibleTab = function (callback) {
         chrome.tabs.captureVisibleTab(null, {format: 'png', quality: 100}, uri => {
@@ -222,93 +223,17 @@ let BgPageInstance = (function () {
         });
     };
 
-    let _screenCapture = function(params){
-
-        // 将Blob数据存储到本地临时文件
-        function saveBlob(blob, filename, index, callback, errback) {
-            filename = ((filename, index) => {
-                if (!index) {
-                    return filename;
-                }
-                let sp = filename.split('.');
-                let ext = sp.pop();
-                return sp.join('.') + '-' + (index + 1) + '.' + ext;
-            })(filename, index);
-            let urlName = `filesystem:chrome-extension://${chrome.i18n.getMessage('@@extension_id')}/temporary/${filename}`;
-
-            let size = blob.size + (1024 / 2);
-
-            let reqFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
-            reqFileSystem(window.TEMPORARY, size, function (fs) {
-                fs.root.getFile(filename, {create: true}, function (fileEntry) {
-                    fileEntry.createWriter(function (fileWriter) {
-                        fileWriter.onwriteend = () => callback(urlName);
-                        fileWriter.write(blob);
-                    }, errback);
-                }, errback);
-            }, errback);
-        }
-
-        function reallyDone(imgUrl) {
-            params.fileSystemUrl = imgUrl;
-            let sendDataUri = tab => {
-                chrome.tabs.sendMessage(tab.id, {
-                    type: 'page-screenshot-done',
-                    data: params
-                });
-            };
-            if (!params.resultTab) {
-                chrome.tabs.create({
-                    url: 'dynamic/index.html?tool=screenshot',
-                    active: true
-                }, (tab) => {
-                    setTimeout((tab => {
-                        return () => sendDataUri(tab);
-                    })(tab), 500);
-                });
-            } else {
-                chrome.tabs.update(params.resultTab, {highlighted: true, active: true}, sendDataUri);
-            }
-        }
-
-        // 获取Blobs数据
-        function getBlobs(dataUris) {
-            return dataUris.map(function (uri) {
-                let byteString = atob(uri.split(',')[1]);
-                let mimeString = uri.split(',')[0].split(':')[1].split(';')[0];
-                let ab = new ArrayBuffer(byteString.length);
-                let ia = new Uint8Array(ab);
-                for (let i = 0; i < byteString.length; i++) {
-                    ia[i] = byteString.charCodeAt(i);
-                }
-                return new Blob([ab], {type: mimeString});
-            });
-        }
-
-        function wellDone(dus) {
-            let blobs = getBlobs(dus);
-            let i = 0;
-            let len = blobs.length;
-
-            // 保存 & 打开
-            (function doNext() {
-                saveBlob(blobs[i], params.filename, i, function (imgUrl) {
-                    ++i >= len ? reallyDone(imgUrl) : doNext();
-                }, reallyDone);
-            })();
-        }
-
-        wellDone(params.dataUris);
-    };
-
-    let _addScreenShotByPages = function(params){
+    let _addScreenShotByPages = function(params,callback){
         chrome.tabs.captureVisibleTab(null, {format: 'png', quality: 100}, uri => {
-            let code = `window.addScreenShot(${JSON.stringify(params)},'${uri}');`
-            InjectTools.inject(params.tabInfo.id, { code });
+            callback({ params,uri });
         });
+    };
 
-        let code = `window.addScreenShot(${JSON.stringify(params)},'${uri}');`
-        InjectTools.inject(params.tabInfo.id, { code: `window.captureCallback();` });
+    let _showScreenShotResult = function(data){
+        chrome.DynamicToolRunner({
+            tool: 'screenshot',
+            withContent: data
+        });
     };
 
     let _colorPickerCapture = function(params) {
@@ -429,11 +354,11 @@ let BgPageInstance = (function () {
                     case 'color-picker-capture':
                         _colorPickerCapture(request.params);
                         break;
-                    case 'screen-capture':
-                        _screenCapture(request.params);
-                        break;
                     case 'add-screen-shot-by-pages':
-                        _addScreenShotByPages(request.params);
+                        _addScreenShotByPages(request.params,callback);
+                        return true;
+                    case 'page-screenshot-done':
+                        _showScreenShotResult(request.params);
                         break;
                     case 'request-monkey-start':
                         Monkey.start(request.params);

+ 1 - 1
apps/background/tools.js

@@ -171,7 +171,7 @@ let toolMap = {
         name: '网页截屏工具',
         tips: '可对任意网页进行截屏,支持可视区域截屏、全网页滚动截屏,最终结果可预览后再保存',
         contentScriptJs: true,
-        // noPage: true,
+        noPage: true,
         menuConfig: [{
             icon: '✂',
             text: 'FH开发者工具'

+ 47 - 35
apps/screenshot/content-script.js

@@ -2,13 +2,14 @@
  * FeHelper Full Page Capture
  * @type {{scroll}}
  */
-window.screenshotContentScript = function (params) {
+window.screenshotContentScript = function () {
 
     let screenshots = [];
     let capturedData = {};
     let MAX_PRIMARY_DIMENSION = 50000 * 2,
         MAX_SECONDARY_DIMENSION = 20000 * 2,
         MAX_AREA = MAX_PRIMARY_DIMENSION * MAX_SECONDARY_DIMENSION;
+    let pageOriginalTitle = document.title;
 
     /**
      * URL合法性校验
@@ -61,10 +62,8 @@ window.screenshotContentScript = function (params) {
         for (row = 0; row < numRows; row++) {
             for (col = 0; col < numCols; col++) {
                 canvas = document.createElement('canvas');
-                canvas.width = (col === numCols - 1 ? totalWidth % maxWidth || maxWidth :
-                    maxWidth);
-                canvas.height = (row === numRows - 1 ? totalHeight % maxHeight || maxHeight :
-                    maxHeight);
+                canvas.width = (col === numCols - 1 ? totalWidth % maxWidth || maxWidth : maxWidth);
+                canvas.height = (row === numRows - 1 ? totalHeight % maxHeight || maxHeight : maxHeight);
 
                 left = col * maxWidth;
                 top = row * maxHeight;
@@ -110,7 +109,7 @@ window.screenshotContentScript = function (params) {
     }
 
 
-    window.addScreenShot = function (data, uri) {
+    let addScreenShot = function (data, uri) {
         let image = new Image();
 
         image.onload = function () {
@@ -148,7 +147,7 @@ window.screenshotContentScript = function (params) {
             });
 
             if (data.complete === 1) {
-                captureConfig.success();
+                captureConfig.success(data);
             }
         };
         image.src = uri;
@@ -160,8 +159,8 @@ window.screenshotContentScript = function (params) {
      * @param contentURL
      * @returns {string}
      */
-    function buildFilenameFromUrl(contentURL) {
-        let name = contentURL.split('?')[0].split('#')[0];
+    function buildFilenameFromUrl() {
+        let name = location.href.split('?')[0].split('#')[0];
         if (name) {
             name = name
                 .replace(/^https?:\/\//, '')
@@ -176,23 +175,23 @@ window.screenshotContentScript = function (params) {
         return 'fehelper' + name + '-' + Date.now() + '.png';
     }
 
+
     // 配置项
     let captureConfig = {
         // 获取原始数据,用这个
-        success: function () {
-
-            // 生成临时文件名
-            capturedData = {
-                pageInfo: params.tabInfo,
-                resultTab: params.captureInfo.resultTab,
-                filename: buildFilenameFromUrl(params.tabInfo.url),
-                dataUris: screenshots.map(ss => ss.canvas.toDataURL())
-            };
-
+        success: function (data) {
             chrome.runtime.sendMessage({
                 type: 'fh-dynamic-any-thing',
-                thing: 'screen-capture',
-                params: capturedData
+                thing: 'page-screenshot-done',
+                params: {
+                    filename: buildFilenameFromUrl(),
+                    screenshots: screenshots.map(ss => {
+                        ss.dataUri=ss.canvas.toDataURL()
+                        return ss;
+                    }),
+                    totalWidth: data.totalWidth,
+                    totalHeight: data.totalHeight
+                }
             });
         },
 
@@ -206,7 +205,7 @@ window.screenshotContentScript = function (params) {
 
             if (percent === '100%') {
                 setTimeout(() => {
-                    document.title = params.tabInfo.title;
+                    document.title = pageOriginalTitle;
                 }, 800);
             }
 
@@ -221,9 +220,9 @@ window.screenshotContentScript = function (params) {
         }));
     }
 
-    function goCapture() {
+    function goCapture(params) {
 
-        if (!isValidUrl(params.tabInfo.url)) {
+        if (!isValidUrl(location.href)) {
             return captureConfig.fail('invalid url');
         }
 
@@ -274,7 +273,7 @@ window.screenshotContentScript = function (params) {
         document.documentElement.style.overflow = 'hidden';
 
         // 截图:可视区域
-        if (params.captureInfo.captureType === 'visible') {
+        if (params.captureType === 'visible') {
             arrangements = [window.scrollX, window.scrollY];
             fullWidth = window.innerWidth;
             fullHeight = window.innerHeight;
@@ -327,8 +326,7 @@ window.screenshotContentScript = function (params) {
                 totalWidth: fullWidth,
                 totalHeight: fullHeight,
                 devicePixelRatio: window.devicePixelRatio,
-                tabInfo: params.tabInfo,
-                captureInfo: params.captureInfo
+                tabId: window.__FH_TAB_ID__
             };
 
             // Need to wait for things to settle
@@ -338,23 +336,37 @@ window.screenshotContentScript = function (params) {
 
                 captureConfig.progress(data.complete);
 
-                window.captureCallback = function () {
+                chrome.runtime.sendMessage({
+                    type: 'fh-dynamic-any-thing',
+                    thing: 'add-screen-shot-by-pages',
+                    params: data
+                }).then(resp => {
+                    addScreenShot(resp.params,resp.uri);
                     window.clearTimeout(cleanUpTimeout);
                     if (data.complete !== 1) {
                         processArrangements();
                     } else {
                         cleanUp();
                     }
-                };
-
-                chrome.runtime.sendMessage({
-                    type: 'fh-dynamic-any-thing',
-                    thing: 'add-screen-shot-by-pages',
-                    params: data
                 });
             }, 150);
         })();
     }
 
-    return goCapture;
+    window.screenshotNoPage = function(){
+        let elWrapper = document.createElement('div');
+        elWrapper.innerHTML = '<div id="fehelper_screenshot" style="position:fixed;left:0;top:0;right:0;z-index:1000000;padding:15px;background:#000;text-align:center;">' +
+            '<button id="btnVisible" style="margin: 0 10px;padding: 10px;border-radius: 5px;border: 1px solid #fff;cursor:pointer;">可视区域截图</button>' +
+            '<button id="btnWhole" style="margin: 0 10px;padding: 10px;border-radius: 5px;border: 1px solid #fff;cursor:pointer;">全网页截图</button></div>';
+        elAlertMsg = elWrapper.childNodes[0];
+        document.body.appendChild(elAlertMsg);
+        document.querySelector('#btnVisible').onclick = e => {
+            elAlertMsg.remove();
+            goCapture({captureType:'visible'});
+        };
+        document.querySelector('#btnWhole').onclick = e => {
+            elAlertMsg.remove();
+            goCapture({captureType:'whole'});
+        };
+    };
 };

+ 8 - 2
apps/screenshot/index.css

@@ -6,10 +6,14 @@
 
 .img-container {
     overflow-y: scroll;
-    height: 480px;
     border:10px solid #4e5d6c;
     border-right: 0;
     background-color:#4e5d6c;
+    position: absolute;
+    bottom: 0;
+    top: 120px;
+    left: 0;
+    right: 0;
 }
 
 .img-result {
@@ -62,4 +66,6 @@ th.x-op {
     font-size: 12px;
     font-weight: normal;
     color: #f00;
-}
+    position: relative;
+    top: 5px;
+}

+ 6 - 31
apps/screenshot/index.html

@@ -13,49 +13,24 @@
     <div class="panel panel-default" style="margin-bottom: 0px;">
         <div class="panel-heading">
             <h3 class="panel-title">
-                <a href="http://www.baidufe.com/fehelper/feedback.html" target="_blank" class="x-a-high">
+                <a href="https://www.baidufe.com/fehelper/feedback.html" target="_blank" class="x-a-high">
                     <img src="../static/img/fe-16.png" alt="fehelper"/> FeHelper</a>:网页截屏工具
+                    <span class="x-switch ui-fl-r">Tips:从右键菜单进行网页截屏,效果更佳!(初次安装可能需要重启浏览器哦~~~)</span>
             </h3>
         </div>
     </div>
 
     <div class="panel-body">
-        <div class="row">
-            <h5 class="x-title">&gt;&gt;&nbsp;网页列表
-                <span class="x-switch ui-fl-r">Tips:从右键菜单进行网页截屏,效果更佳!(初次安装可能需要重启浏览器哦~~~)</span>
-            </h5>
-            <table class="table table-bordered table-hover table-striped">
-                <thead>
-                    <tr>
-                        <th class="x-index">序号</th>
-                        <th class="x-tt">标题</th>
-                        <th class="x-url">网址</th>
-                        <th class="x-op">去截屏</th>
-                    </tr>
-                </thead>
-                <tbody>
-                    <tr v-for="(tab,index) in tabList">
-                        <td>{{index + 1}}</td>
-                        <td>{{tab.title}}</td>
-                        <td>{{tab.url}}</td>
-                        <td>
-                            <button class="btn btn-primary btn-sm" @click="goCapture(tab.id,'visible')">可视区域截屏</button>
-                            <button class="btn btn-success btn-sm" @click="goCapture(tab.id,'whole')">完整页面截屏</button>
-                        </td>
-                    </tr>
-                </tbody>
-            </table>
-        </div>
-
-        <div class="row" ref="resultBox" v-show="!!imageHTML">
+        <div class="row" ref="resultBox" >
             <h5 class="x-title c-d">&gt;&gt;&nbsp;完整截图
                 <input id="btnSave" class="btn btn-warning btn-sm ui-fl-r" type="button" value="保存图片到本地" @click="save">
             </h5>
-            <div class="panel panel-default img-container" id="imageEditor" v-html="imageHTML"></div>
+            <div class="panel panel-default img-container" id="imageEditor">
+                <canvas :width="totalWidth" :height="totalHeight"></canvas>
+            </div>
         </div>
     </div>
 </div>
-<script type="text/javascript" src="content-script.js"></script>
 <script type="text/javascript" src="index.js"></script>
 </body>
 </html>

+ 34 - 125
apps/screenshot/index.js

@@ -7,141 +7,50 @@ new Vue({
         tabList: [],
         capturedImage: '',
         imageHTML: '',
-        defaultFilename: Date.now() + '.png'
+        defaultFilename: Date.now() + '.png',
+        totalWidth: 100,
+        totalHeight: 100
     },
     mounted: function () {
-
-        this.updateTabList();
-        this.bindEvent();
-
-    },
-    methods: {
-
-        bindEvent: function () {
-            chrome.tabs.onCreated.addListener(tab => {
-                if (/^http(s)?:\/\//.test(tab.url)) {
-                    this.tabList.push({
-                        id: tab.id,
-                        title: tab.title,
-                        url: tab.url
-                    });
-                }
-            });
-            chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
-                this.tabList.some((t, index) => {
-                    if (t.id === tabId) {
-                        t.title = tab.title;
-                        t.url = tab.url;
-                        return true;
-                    }
-                    return false;
-                });
-            });
-            chrome.tabs.onRemoved.addListener(tabId => {
-                this.tabList.some((tab, index) => {
-                    if (tab.id === tabId) {
-                        this.tabList.splice(index, 1);
-                        return true;
-                    }
-                    return false;
+        // 在tab创建或者更新时候,监听事件,看看是否有参数传递过来
+        if (location.protocol === 'chrome-extension:') {
+            chrome.tabs.query({currentWindow: true,active: true, }, (tabs) => {
+                let activeTab = tabs.filter(tab => tab.active)[0];
+                chrome.runtime.sendMessage({
+                    type: 'fh-dynamic-any-thing',
+                    thing: 'request-page-content',
+                    tabId: activeTab.id
+                }).then(resp => {
+                    if(!resp || !resp.content) return ;
+                    this.showResult(resp.content);
                 });
             });
+        }
+    },
+    methods: {
 
-            chrome.runtime.onMessage.addListener((request, sender, callback) => {
-                if (request.type === 'page-screenshot-done') {
-                    let capturedData = request.data;
-                    if (capturedData && capturedData.fileSystemUrl) {
-                        this.capturedImage = capturedData.fileSystemUrl;
-                        this.imageHTML = `<img class="img-result" src="${this.capturedImage}" />`;
-                        this.defaultFilename = capturedData.filename;
-
-                        this.$nextTick(() => {
-                            this.$refs.resultBox.scrollIntoView();
-                        });
-
-                        chrome.tabs.get(capturedData.pageInfo.id, tab => {
-                            this.tabList.some(t => {
-                                if (t.id === tab.id) {
-                                    t.title = tab.title;
-                                    return true;
-                                }
-                                return false;
-                            });
-                        });
-                    }
-                }
-                callback && callback();
-                return true;
-            });
-        },
+        showResult: function(data){
+            if (data && data.screenshots) {
+                this.totalWidth = data.totalWidth;
+                this.totalHeight = data.totalHeight;
+                let canvas = document.querySelector('#imageEditor>canvas');
+                let ctx  = canvas.getContext('2d');
 
-        updateTabList: function () {
-            chrome.tabs.query({windowId: chrome.windows.WINDOW_ID_CURRENT}, tabs => {
-                this.tabList = tabs.filter(tab => {
-                    return /^http(s)?:\/\//.test(tab.url)
-                }).map(tab => {
-                    return {
-                        id: tab.id,
-                        title: tab.title,
-                        url: tab.url
+                data.screenshots.forEach((ss) => {
+                    let img = new Image();
+                    img.dx = ss.left;
+                    img.dy = ss.top;
+                    img.onload = function(event){
+                        ctx.drawImage(this,this.dx,this.dy,this.width,this.height);
                     };
+                    img.src = ss.dataUri;
                 });
-            });
-        },
-
-        goCapture: function (tabId, captureType) {
-            chrome.tabs.getCurrent(curTab => {
-                chrome.tabs.query({windowId: chrome.windows.WINDOW_ID_CURRENT}, (tabs) => {
-                    let found = tabs.some(tab => tab.id === tabId);
+                this.defaultFilename = data.filename;
 
-                    if (found) {
-                        chrome.tabs.update(tabId, {highlighted: true, active: true}, tab => {
-
-                            // 没有文件就只注入脚本
-                            // chrome.scripting.executeScript({
-                            //     target: {tab.id, allFrames: false},
-                            //     func: function(code){evalCore.getEvalInstance(window)(code)},
-                            //     args: [codeConfig.code]
-                            // }, function () {
-                            //     try {
-                            //         callback && callback.apply(this, arguments);
-                            //     } catch (e) {
-                            //         callback && callback(null);
-                            //     }
-                            // });
-
-                            chrome.tabs.executeScript(tab.id, {
-                                code: '(' + (function (tabInfo, captureInfo) {
-                                    chrome.runtime.sendMessage({
-                                        type: 'fh-dynamic-any-thing',
-                                        params: {
-                                            tabInfo: tabInfo,
-                                            captureInfo: captureInfo
-                                        },
-                                        func: ((params, callback) => {
-                                            try {
-                                                callback && callback(params);
-                                            } catch (e) {
-                                                callback && callback(null);
-                                            }
-                                            return true;
-                                        }).toString()
-                                    }, (params) => {
-                                        let func = window['screenshotContentScript'];
-                                        func && func(params)();
-                                    });
-                                }).toString() + ')(' + JSON.stringify(tab) + ',' + JSON.stringify({
-                                    resultTab: curTab.id,
-                                    captureType: captureType
-                                }) + ')',
-                                allFrames: false
-                            });
-                        });
-                    } else {
-                        alert('页面已关闭');
-                    }
+                this.$nextTick(() => {
+                    this.$refs.resultBox.scrollIntoView();
                 });
-            });
+            }
         },
 
         save: function () {