IT Share you

HTML 책과 같은 페이지 매김

shareyou 2020. 12. 8. 20:26
반응형

HTML 책과 같은 페이지 매김


WebKit 브라우저에서 HTML 파일의 내용을 화면 크기의 청크로 분할하여 "페이지 매김"하려면 어떻게해야합니까?

각 "페이지"에는 완전한 양의 텍스트가 표시되어야합니다. 즉, 화면의 위쪽 또는 아래쪽 테두리에서 텍스트 줄을 반으로 잘라서는 안됩니다.

편집하다

이 질문은 원래 Android ePub 리더를 구축하는 것이므로 "Android"태그가 지정되었습니다. 하지만이 솔루션은 JavaScript와 CSS만으로 구현할 수있는 것으로 보이므로 플랫폼 독립적으로 만들기 위해 질문의 범위를 넓혔습니다.


여기서 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;

도움이 되었기를 바랍니다...


경험을 바탕으로 말하면, 베어 본 시청자에게도 많은 시간을 할애 할 수 있습니다. ePub 리더는 실제로 제가 C #을 배우기 시작했을 때 수행 한 첫 번째 큰 프로젝트 였지만 ePub 표준은 확실히 꽤 복잡합니다.

ePub의 최신 버전은 http://www.idpf.org/specs.htm 에서 찾을 수 있습니다. 여기 에는 OPS (Open Publication Structure), OPF (Open Packaging Format) 및 OCF (OEBPS Container Format)가 포함됩니다. .

또한 도움이된다면 내가 시작한 프로젝트의 C # 소스 코드에 대한 링크가 있습니다.

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

전혀 구체화되지 않았습니다. 나는 몇 달 동안 이것을 가지고 놀지 않았지만 올바르게 기억한다면 디버그 디렉토리에 ePub를 붙이고 프로그램을 실행할 때 이름의 일부를 입력하기 만하면됩니다 (예 : Under the Dome, 그냥 "dome"입력). 책의 세부 사항이 표시됩니다.

몇 권의 책에서 제대로 작동했지만 Google 도서의 모든 eBook이 완전히 망가졌습니다. 그들은 다른 출처의 책에 비해 완전히 기괴한 ePub 구현을 가지고 있습니다 (적어도 나에게는).

어쨌든, 구조 코드 중 일부가 도움이 될 수 있기를 바랍니다!


나는 이와 같은 코드를 작성해야했고 내 (작동하는) 솔루션은 다음과 같습니다.

이 라인을 웹뷰에 적용해야합니다 ...

    webView_.getSettings().setUseWideViewPort(true);
    webView_.getSettings().setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS);

또한 자바 스크립트를 삽입해야합니다. 내 활동의 규모와 웹뷰에서 렌더링 된 콘텐츠에 많은 문제가 있었기 때문에 내 솔루션은 "외부"에서 어떠한 가치도 취하지 않습니다.

    webView_.setWebViewClient(new WebViewClient(){

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

        });

[...]

    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()");
    }

즐겨 :)


최근에 이와 비슷한 것을 시도하고 레이아웃을 세로 대신 가로로 변경하기 위해 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");

따라서 기본적으로 챕터가로드 된 후 본문 요소의 스타일을 변경하기 위해 JavaScript를 삽입합니다 (매우 중요). 이 접근 방식의 유일한 단점은 콘텐츠에 이미지가있을 때 계산 된 열 수가 비스듬하게되는 것입니다. 그래도 고치는 것이 너무 어렵지는 않습니다. 내 시도는 DOM의 모든 이미지에 너비와 높이 속성을 추가하기 위해 JavaScript를 삽입하려고했습니다.

도움이 되었기를 바랍니다.

-단


아마도 XSL-FO 를 사용하는 것이 좋습니다 . 이것은 모바일 장치에서는 무겁고 과도하게 작동 할 수도 있지만 작동해야하며 복잡한 페이지 매김을 구현할 필요가 없습니다 (예 : 각 화면이 텍스트를 반으로 자르지 않도록하는 방법). .

기본 아이디어는 다음과 같습니다.

  • XSLT를 사용하여 XHTML (및 기타 EPUB 항목)을 XSL-FO로 변환합니다.
  • XSL-FO 프로세서를 사용하여 XSL-FO를 PDF와 같이 모바일 장치에 표시 할 수있는 페이지 형식으로 렌더링합니다 (표시 할 수 있습니까?).

Android에서 사용할 수있는 XSL-FO 프로세서가 있는지 모르겠습니다. Apache FOP를 사용해 볼 수 있습니다. RenderX (XSL-FO 프로세서)는 페이지 된 HTML 출력 옵션 이 있다는 장점이 있지만 Android에서 실행할 수 있는지는 모르겠습니다.


이를 수행 할 수있는 몇 가지 방법이 있습니다. 모든 행이 자체 요소에있는 경우 해당 모서리 중 하나가 뷰 (브라우저 또는 "책 페이지")를 벗어나는지 확인하기 만하면됩니다.

얼마나 많은 "페이지"가 ​​미리 있을지 알고 싶다면 일시적으로보기로 이동하여 페이지가 끝나는 줄을 가져옵니다. 브라우저가 어디에 있는지 알기 위해 페이지 리플 로우가 필요하기 때문에 이것은 잠재적으로 느려질 수 있습니다.

그렇지 않으면 HTML5 캔버스 요소를 사용하여 텍스트를 측정하거나 텍스트를 그릴 수 있다고 생각합니다.

여기에 대한 몇 가지 정보 : https://developer.mozilla.org/en/Drawing_text_using_a_canvas http://uupaa-js-spinoff.googlecode.com/svn/trunk/uupaa-excanvas.js/demo/8_2_canvas_measureText.html


최근에 동일한 문제가 발생하고 답변에서 영감을 받아 CSS3의 column- * 속성을 사용하는 일반 CSS 솔루션을 찾았습니다.

/* CSS */
.chapter {
    width: 600px;
    padding: 60px 10px;
    -webkit-column-gap: 40px;
    -webkit-column-width: 150px;
    -webkit-column-count: 2;
    height:400px;
}

/* HTML */
<div class="chapter">
    your long lorem ipsum arbitrary HTML
</div>

위의 예는 Retina iPhone에서 훌륭한 결과를 제공합니다. 다른 속성을 가지고 놀면 페이지 사이의 간격이 달라집니다.

예를 들어 새 페이지에서 시작해야하는 여러 장을 지원해야하는 경우 github에 XCode 5 예제가 있습니다. https://github.com/dmrschmidt/ios_uiwebview_pagination


WebView로 수평 스 와이프 페이징 효과를 얻기 위해 Nacho의 솔루션 을 개선 할 수있었습니다 . 여기에서 솔루션 과 예제 코드를 찾을 수 있습니다 .

편집하다:

솔루션 코드.

MainActivity.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())");
}

내 WebChromeClient의 onJsAlert에서 페이징 효과를 구현하기 위해 사용자 정의 HorizontalWebView에 전달하는 가로 페이지 수를 가져옵니다.

HorizontalWebView.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;
    }
}

페이지를 별도의 XHTML 파일로 분할하여 폴더에 저장할 수 있습니다. 예 : page01, page02. 그런 다음 해당 페이지를 서로 아래에 하나씩 렌더링 할 수 있습니다.


You can look at http://www.litres.ru/static/OR/or.html?data=/static/trials/00/42/47/00424722.gur.html&art=424722&user=0&trial=1 but the code may be heavily obfuscated, so just use Firebug to inspect DOM.

If the link isn't working, comment - would give you fixed.

참고URL : https://stackoverflow.com/questions/3636052/html-book-like-pagination

반응형