Extjs6+svg实现类似pdf图片预览页面

一、创建项目

本项目采用的是extjs6.2,话说个人感觉ext4到ext6变化其实也并不大,大部分之前写的ext4的代码迁移至ext6上,并没有太大的问题,修改的地方并不多。至于前端项目是否采用cmd进行创建,看个人喜欢。本人是不太喜欢,虽然编译后代码做了压缩,但是页面耦合性太紧,很难共用某些页面(iframe)方式。废话少说,具体实现页面如下:


主要分两部分,左侧为导航栏(文档缩略图),右侧为文档主视图;

设计思想是把它作为单独模块,能够被其他页面所引用,所以建一个文件以document命名,其他页面要引用直接Ext.create或者iframe方式就行了。

document下的文件有:Config.js(配置页)、Document.js(主入口页)、PageIndex.js(左侧菜单栏)、PagePanel.js(主视图页)、PageSvg.js(主视图svg)、Statusbar.js(工具栏);

document.js负责装载PageIndex和PagePanel两个主件;

Ext.define('App.document.Document', {
    extend: 'Ext.panel.Panel',
    layout: 'border',
    initComponent: function () {
        var me = this;
        me.pageIndex = Ext.create('App.document.PageIndex', {
            region: 'west',
            scrollable: 'y',
            width: '10%',
            split: true,
            parent: me
        });
        me.pagePanel = Ext.create('App.document.PagePanel', {
            region: 'center',
            parent: me
        });
        me.items = [me.pageIndex, me.pagePanel];
        me.callParent(arguments);
    }
});
接着是左侧导航栏PageIndex.js,用容器Ext.container.Container装载Ext.Img和Ext.form.Label:

Ext.define('App.document.PageIndex', {
    extend: 'Ext.panel.Panel',
    requires: [
        'Ext.Img',
        'Ext.form.Label'
    ],
    title: '文档页导航',
    autoScroll: true,
    layout: 'column',
    frame: true,
    collapsible: true,
    currentPage: null,
    load: function (doc) {
        var me = this, pageList = [];
        for (var i = 0; i < doc.total; i++) {
            var url = url;
            pageList[i] = Ext.create('Ext.container.Container', {
                layout: 'column',
                items: [
                    Ext.create('Ext.Img', {
                        margin: '10 15 10 15',
                        columnWidth: 1,
                        src: url
                    }),
                    Ext.create('Ext.form.Label', {
                        columnWidth: 1,
                        cls: 'PageCode',
                        text: (i + 1),
                        style: 'text-align:center'
                    })
                ],
                columnWidth: 1,
                margin: '20 40 20 20',
                border: 2,
                style: {
                    borderColor: 'red',
                    borderStyle: 'hidden'
                }
            });
        }
        me.add(pageList);
    }
});
完成了左侧导航栏后,接着是主视图 PagePanel,投机取巧的方法是采用和左侧导航栏相同的方式实现,不过这里存在个问题,当页面多的时候,滑动会卡;因为本人会对主视图进行编辑等操作,故不用此方式,转而用svg的方式实现,同时为了避免卡顿,默认只显示两页,代码如下:
Ext.define('App.document.PagePanel', {
    extend: 'Ext.panel.Panel',
    layout: 'absolute',
    frame: false,
    autoScroll: true,
    reality: null,
    initComponent: function () {
        var me = this;
        me.bbar = me.statusbar = Ext.create('App.document.Statusbar', {});
        me.callParent(arguments);
    },
    load: function (doc) {
        var me = this;
        me.doc = doc;
        var next = me.body.first();
        while (next) {
            next.setSize(0, 0);
            next = next.next();
        }
        me.pageMap = {};
        for (var i = 0; i < doc.total; i++) {
            me.pageMap[i] = Ext.create('App.document.PageSvg', {
                canvas: me,
                parent: me,
                doc: doc,
                page: i
            });
        }
    }
});

PageSvg.js

Ext.define('App.document.PageSvg', {
    hidden: true,
    layers: null,
    constructor: function (config) {
        var me = this;
        if (config) {
            Ext.apply(me, config);
        }
        me.init();
    },
    init: function () {
        var me = this;
        me.layers = {};
        me.body = me.canvas.body.createChild();
        me.buildHTML();
    },
    getDPI: function () {
        var dpiX, dpiY;
        if (window.screen.deviceXDPI != undefined) {
            dpiX = window.screen.deviceXDPI;
            dpiY = window.screen.deviceYDPI;
        } else {
            var tmpNode = document.createElement("DIV");
            tmpNode.style.cssText = "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
            document.body.appendChild(tmpNode);
            dpiX = parseInt(tmpNode.offsetWidth);
            dpiY = parseInt(tmpNode.offsetHeight);
            tmpNode.parentNode.removeChild(tmpNode);
        }
        return dpiX === dpiY ? dpiX : {dpiX: dpiX, dpiY: dpiY};
    },
    buildHTML: function () {
        var me = this, canvas = me.canvas, reality = canvas.reality, scale = me.parent.getPageScale();
        var doc = me.doc, pageInfo = doc.children[me.page];
        me.realHeight = (pageInfo.height * 2.54 / (pageInfo.ydpi || me.getDPI())).toFixed(2);
        me.realWidth = (pageInfo.width * 2.54 / (pageInfo.xdpi || me.getDPI()));
        var margin = (reality || canvas).getPageMargin() * scale, width = (reality || canvas).body.getWidth();
        me.realWidth = parseInt(me.realWidth * me.getDPI() / 2.54);
        width = width > me.realWidth ? width : me.realWidth;
        var layer_name = 'page';
        me.layers[layer_name] = {
            tag: 'g',
            name: layer_name,
            children: [
                {
                    tag: 'image',
                    width: pageInfo.width,
                    height: pageInfo.height,
                    style: 'border: 1px solid #000',
                    'xlink:href': url
                }
            ]
        };
        var children = [];
        for (var key in me.layers) {
            children.push(me.layers[key]);
        }
        var svg = {
            tag: 'svg',
            width: (width * scale) - 40,
            height: me.realHeight * scale + 'cm',
            viewBox: '0 0 {width} {height}'.replace('{width}', pageInfo.width).replace('{height}', pageInfo.height),
            preserveAspectRatio: 'xMidYMin meet',
            style: 'margin:' + [margin, margin, margin, margin].join(' '),
            children: me.hidden ? null : children
        };
        var svgHtml = Ext.DomHelper.markup(svg);
        me.body.setHtml('');
        me.body.setHtml(svgHtml);
        me.svg = me.body.child('svg');
    },
    onScale: function () {
        var me = this;
        me.buildHTML();
    },
    show: function () {
        var me = this;
        me.hidden = false;
        me.buildHTML();
    },
    hide: function () {
        var me = this;
        me.hidden = true;
        me.buildHTML();
    }
});
Statusbar.js

Ext.define('App.document.Statusbar', {
    extend: 'Ext.toolbar.Toolbar',
    initComponent: function () {
        var me = this;
        me.pageDisplay = Ext.create('Ext.form.Field', {
            width: 100,
            originValue: '第{page}/{pageTotal}' + '页'
        });
        me.items = ['->', me.pageDisplay, '->'];
        me.callParent(arguments);
    },
    paging: function (page, total) {
        var me = this;
        me.pageDisplay.setValue(me.pageDisplay.originValue
                .replace('{page}', page + 1)
                .replace('{pageTotal}', total));
    }
});

大概就是这样,还有一些点击触发事件,以及页面编辑的事件,可以在这里的基础上进行扩展;








  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值