HTML书籍式的分页

hpi*_*que 59 html javascript css pagination webkit

如何在屏幕大小的块中拆分HTML文件的内容,以便在WebKit浏览器中"分页"它?

每个"页面"应显示完整的文本量.这意味着不得在屏幕的顶部或底部边框中将一行文本切成两半.

编辑

这个问题最初标记为"Android",因为我打算构建一个Android ePub阅读器.但是,似乎解决方案只能使用JavaScript和CSS实现,因此我扩大了问题的范围,使其与平台无关.

Eng*_*epe 30

基于Dan的答案,这是我解决这个问题的方法,直到现在我一直在努力解决这个问题.(这个JS适用于iOS Webkit,不保证android,但请告诉我结果)

var desiredHeight;
var desiredWidth;
var bodyID = document.getElementsByTagName('body')[0];
totalHeight = bodyID.offsetHeight;
pageCount = Math.floor(totalHeight/desiredHeight) + 1;
bodyID.style.padding = 10; //(optional) prevents clipped letters around the edges
bodyID.style.width = desiredWidth * pageCount;
bodyID.style.height = desiredHeight;
bodyID.style.WebkitColumnCount = pageCount;
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助...

  • 你能指导我如何在webview中实现这个吗?或者你可以为此发布完整的代码?提前致谢. (6认同)

kco*_*ock 21

从经验来看,即使对于准系统观众来说,也希望花费大量时间.当我开始学习C#时,ePub阅读器实际上是我开始学习的第一个大项目,但ePub标准肯定非常复杂.

您可以在此处找到ePub规范的最新版本:http: //www.idpf.org/specs.htm ,其中包括OPS(开放出版物结构),OPF(开放式包装格式)和OCF(OEBPS容器格式​​) .

此外,如果它对您有所帮助,这里是我开始的项目的C#源代码的链接:

https://www.dropbox.com/sh/50kxcr29831t854/MDITIklW3I/ePub%20Test.zip

它根本没有充实; 我好几个月都没玩过,但是如果我没记错的话,只需在调试目录中粘贴一个ePub,当你运行程序时只需输入名称的某些部分(例如在圆顶下,只需输入"圆顶")它将显示该书的详细信息.

我让它适用于几本书,但Google Books中的任何电子书都完全破坏了它.与来自其他来源的书籍相比,他们对ePub(至少对我而言)有一个完全奇怪的实现.

无论如何,希望那里的一些结构代码可以帮助你!


Nac*_* L. 18

我也必须编写类似这样的代码,我的(工作)解决方案是这样的:

您必须将这些行应用于webview ...

    webView_.getSettings().setUseWideViewPort(true);
    webView_.getSettings().setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS);
Run Code Online (Sandbox Code Playgroud)

此外,你必须注入一些JavaScript.我的活动的不同比例和webview中呈现的内容有很多问题,因此我的解决方案不会从"外部"获取任何值.

    webView_.setWebViewClient(new WebViewClient(){

            public void onPageFinished(WebView view, String url) {
                injectJavascript();
            }

        });
Run Code Online (Sandbox Code Playgroud)

[...]

    public void injectJavascript() {
        String js = "javascript:function initialize() { " +
                "var d = document.getElementsByTagName('body')[0];" +
                "var ourH = window.innerHeight; " +
                "var ourW = window.innerWidth; " + 
                "var fullH = d.offsetHeight; " +
                "var pageCount = Math.floor(fullH/ourH)+1;" +
                "var currentPage = 0; " +
                "var newW = pageCount*ourW; " +
                "d.style.height = ourH+'px';" +
                "d.style.width = newW+'px';" +
                "d.style.webkitColumnGap = '2px'; " +
                "d.style.margin = 0; " +
                "d.style.webkitColumnCount = pageCount;" +
                "}";
        webView_.loadUrl(js);
        webView_.loadUrl("javascript:initialize()");
    }
Run Code Online (Sandbox Code Playgroud)

请享用 :)


Dan*_*Dan 12

我最近尝试了类似的东西并添加了一些CSS样式来将布局更改为水平而不是垂直.这给了我期望的效果,而不必以任何方式修改Epub的内容.

这段代码应该有效.

mWebView.setWebViewClient(new WebViewClient() {
    public void onPageFinished(WebView view, String url) {

        // Column Count is just the number of 'screens' of text. Add one for partial 'screens'
        int columnCount = Math.floor(view.getHeight() / view.getWidth())+1;

        // Must be expressed as a percentage. If not set then the WebView will not stretch to give the desired effect.
        int columnWidth = columnCount * 100;

        String js = "var d = document.getElementsByTagName('body')[0];" + 
            "d.style.WebkitColumnCount=" + columnCount + ";" + 
            "d.style.WebkitColumnWidth='" + columnWidth + "%';";
        mWebView.loadUrl("javascript:(function(){" + js + "})()");
    }
});

mWebView.loadUrl("file:///android_asset/chapter.xml");
Run Code Online (Sandbox Code Playgroud)

所以,基本上你是在注入章节之后注入JavaScript来改变body元素的样式(非常重要).这种方法的唯一缺点是当内容中的图像计算出的列数歪斜时.虽然它不应该太难修复.我的尝试是注入一些JavaScript来为DOM中没有任何图像的所有图像添加宽度和高度属性.

希望能帮助到你.

-担


Gau*_*bde 5

我能够改进Nacho 的解决方案,以通过 WebView 获得水平滑动分页效果。您可以在此处找到解决方案和示例代码

编辑:

解决方案代码。

主活动.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        WebView.setWebContentsDebuggingEnabled(true);
    }
    wv = (HorizontalWebView) findViewById(R.id.web_view);
    wv.getSettings().setJavaScriptEnabled(true);
    wv.setWebViewClient(new WebViewClient() {

        public void onPageFinished(WebView view, String url) {
            injectJavascript();
        }
    });

    wv.setWebChromeClient(new WebChromeClient() {
        @Override
        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
            int pageCount = Integer.parseInt(message);
            wv.setPageCount(pageCount);
            result.confirm();
            return true;
        }
    });
    wv.loadUrl("file:///android_asset/ch03.html");   // now it will not fail here
}

private void injectJavascript() {
    String js = "function initialize(){\n" +
            "    var d = document.getElementsByTagName('body')[0];\n" +
            "    var ourH = window.innerHeight;\n" +
            "    var ourW = window.innerWidth;\n" +
            "    var fullH = d.offsetHeight;\n" +
            "    var pageCount = Math.floor(fullH/ourH)+1;\n" +
            "    var currentPage = 0;\n" +
            "    var newW = pageCount*ourW;\n" +
            "    d.style.height = ourH+'px';\n" +
            "    d.style.width = newW+'px';\n" +
            "    d.style.margin = 0;\n" +
            "    d.style.webkitColumnCount = pageCount;\n" +
            "    return pageCount;\n" +
            "}";
    wv.loadUrl("javascript:" + js);
    wv.loadUrl("javascript:alert(initialize())");
}
Run Code Online (Sandbox Code Playgroud)

在我的 WebChromeClient 的 onJsAlert 中获取我传递给自定义 Horizo​​ntalWebView 以实现分页效果的水平页面数

水平WebView.java

public class HorizontalWebView extends WebView {
    private float x1 = -1;
    private int pageCount = 0;

    public HorizontalWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                x1 = event.getX();
                break;
            case MotionEvent.ACTION_UP:
                float x2 = event.getX();
                float deltaX = x2 - x1;
                if (Math.abs(deltaX) > 100) {
                    // Left to Right swipe action
                    if (x2 > x1) {
                        turnPageLeft();
                        return true;
                    }

                    // Right to left swipe action
                    else {
                        turnPageRight();
                        return true;
                    }

                }
                break;
        }
        return true;
    }

    private int current_x = 0;

    private void turnPageLeft() {
        if (getCurrentPage() > 0) {
            int scrollX = getPrevPagePosition();
            loadAnimation(scrollX);
            current_x = scrollX;
            scrollTo(scrollX, 0);
        }
    }

    private int getPrevPagePosition() {
        int prevPage = getCurrentPage() - 1;
        return (int) Math.ceil(prevPage * this.getMeasuredWidth());
    }

    private void turnPageRight() {
        if (getCurrentPage() < pageCount - 1) {
            int scrollX = getNextPagePosition();
            loadAnimation(scrollX);
            current_x = scrollX;
            scrollTo(scrollX, 0);
        }
    }

    private void loadAnimation(int scrollX) {
        ObjectAnimator anim = ObjectAnimator.ofInt(this, "scrollX",
                current_x, scrollX);
        anim.setDuration(500);
        anim.setInterpolator(new LinearInterpolator());
        anim.start();
    }

    private int getNextPagePosition() {
        int nextPage = getCurrentPage() + 1;
        return (int) Math.ceil(nextPage * this.getMeasuredWidth());
    }

    public int getCurrentPage() {
        return (int) (Math.ceil((double) getScrollX() / this.getMeasuredWidth()));
    }

    public void setPageCount(int pageCount) {
        this.pageCount = pageCount;
    }
}
Run Code Online (Sandbox Code Playgroud)