Giter VIP home page Giter VIP logo

stpageflip's Introduction

GitHub license npm npm

StPageFlip

Powerful, simple, and flexible JS Library for creating realistic and beautiful page turning effect.

Features

  • Works with simple images on canvas and complex HTML blocks
  • Has simple API and flexible configuration
  • Compatible with mobile devices
  • Supports landscape and portrait screen mode
  • Supports soft and hard page types (only in HTML mode)
  • No dependencies

Demo and docs: https://nodlik.github.io/StPageFlip/

For React.JS you can use: https://nodlik.github.io/react-pageflip/

Docs (generated by TypeDoc): https://nodlik.github.io/StPageFlip/docs/index.html

Installation

You can install the latest version using npm:

npm install page-flip

Or download bundle from Github

Usage

If you've installed the package from npm, you should import PageFlip from page-flip package, or just use <script/> tag:

<script src="{path/to/scripts}/page-flip.browser.js"></script>

To create a new PageFlip object:

import { PageFlip } from 'page-flip';

const pageFlip = new PageFlip(htmlParentElement, settings);

// or if you're using a script tag and page-flip.browser.js:
const pageFlip = new St.PageFlip(htmlParentElement, settings);

htmlParentElement - HTMLElement- root element, where the book will be created

settings: object - configuration object.

To draw on a canvas, use loadFromImages:

pageFlip.loadFromImages(['path/to/image1.jpg', 'path/to/image2.jpg' ... ]);

To load page from html elements - use loadFromHtml:

pageFlip.loadFromHtml(items);

For example:

<div id="book">
    <div class="my-page" data-density="hard">
        Page Cover
    </div>
    <div class="my-page">
        Page one
    </div>
    <div class="my-page">
        Page two
    </div>
    <div class="my-page">
        Page three
    </div>
    <div class="my-page">
        Page four
    </div>
    <div class="my-page" data-density="hard">
        Last page
    </div>
</div>
const pageFlip = new PageFlip(document.getElementById('book'), {
    width: 400, // required parameter - base page width
    height: 600, // required parameter - base page height
});

pageFlip.loadFromHTML(document.querySelectorAll('.my-page'));

Use data-density="hard" attribute to specify page type (soft | hard) and define flipping animation.

Config

To set configuration define these parameters when creating an object:

  • width: number - required
  • height: number - required
  • size: ("fixed", "stretch") - default: "fixed" Whether the book will be stretched under the parent element or not
  • minWidth, maxWidth, minHeight, maxHeight: number You must set threshold values ​​with size: "stretch"
  • drawShadow: bool - default: true Draw shadows or not when page flipping
  • flippingTime: number (milliseconds) - default: 1000 Flipping animation time
  • usePortrait: bool - default: true Enable switching to portrait mode. !This mode uses cloning of html elements (pages)
  • startZIndex: number - default: 0 Initial value to z-index
  • startPage: number - default: 0 Page number from which to start viewing
  • autoSize: bool - default: true If this value is true, the parent element will be equal to the size of the book
  • maxShadowOpacity: number [0..1] - default: 1 Shadow intensity (1: max intensity, 0: hidden shadows)
  • showCover: boolean - default: false If this value is true, the first and the last pages will be marked as hard and will be shown in single page mode
  • mobileScrollSupport: boolean - default: true disable content scrolling when touching a book on mobile devices
  • swipeDistance: number - default: 30 (px) minimum distance to detect swipe (new on 1.1.0)
  • clickEventForward: boolean - default: true forwarding click events to the page children html elements (only for a and button tags) (new on 1.1.0)
  • useMouseEvents: boolean - default: true using mouse and touch events to page flipping (new on 1.2.0)
  • disableFlipByClick: boolean - default: false if this value is true, flipping by clicking on the whole book will be locked. Clicking will only work in corners (new on 2.0.3)

Events

To listen events use the method on:

pageFlip.on('flip', (e) => {
    // callback code
    alert(e.data); // current page number
});

Available events:

  • flip: number - triggered by page turning
  • changeOrientation: ("portrait", "landscape") - triggered when page orientation changes
  • changeState: ("user_fold", "fold_corner", "flipping", "read") - triggered when the state of the book changes
  • init: ({page: number, mode: 'portrait', 'landscape'}) - triggered when the book is init and the start page is loaded. Listen (on) this event before using the "loadFrom..." methods
  • update: ({page: number, mode: 'portrait', 'landscape'}) - triggered when the book pages are updated (using the "updateFrom..." methods)

Event object has two fields: data: number | string and object: PageFlip

Methods

  • getPageCount: number - Get number of all pages
  • getOrientation: 'portrait', 'landscape' - Get the current orientation: portrait or landscape
  • getBoundsRect: PageRect - Get current book sizes and position
  • getCurrentPageIndex: number - Get the current page number (starts at 0)
  • turnToPage(pageNum: number) - Turn to the specified page number (without animation)
  • turnToNextPage() - Turn to the next page (without animation)
  • turnToPrevPage() - Turn to the previous page (without animation)
  • flipNext(corner: 'top' | 'bottom') - Turn to the next page (with animation)
  • flipPrev(corner: 'top' | 'bottom') - Turn to the previous page (with animation)
  • flip(pageNum: number, corner: 'top' | 'bottom') - Turn to the specified page (with animation)
  • loadFromImages(images: ['path-to-image1.jpg', ...]) - Load page from images
  • loadFromHtml(items: NodeListOf | HTMLElement[]) - Load page from html elements
  • updateFromHtml(items: NodeListOf | HTMLElement[]) - Update page from html elements (new on 0.4.0)
  • updateFromImages(images: ['path-to-image1.jpg', ...]) - Update page from images (new on 0.4.0)
  • destroy() - Destructor. Remove a root HTML element and all event handlers (new on 0.4.0)

Contacts

Oleg,

[email protected]

https://github.com/Nodlik/StPageFlip

Buy me a coffee

stpageflip's People

Contributors

btzr-io avatar nodlik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stpageflip's Issues

Even number of pages - first and last page

Thanks for great library.
One question:
When flipping the second to last page (closing the book) it is still visible under it until the flip animation is over, then it disappears. The shadow is still present.
Similarly if you flip from page 2 to page one (closing the book from front), page 2 is visible under page 2 while it is animating and then the same thing happens.
I thought about introducing 2 additional white pages in the front and at the back to avoid this, but is there any other way to fix this issue?

CSS refresh issue

The v2.0.5 refactoring, while making the code somewhat cleaner, also introduced an issue with the rendering.
See the diff here: 1e302a8#diff-82e2514055cb74ebb7ad8048a1e13c101ca9276fe11790f259e165ac6eadd528

While the CSS renderer could check if the separate style changes really caused changes and only update those styles, setting the cssText directly always rewrites the styles. Since the render updates are going constantly due to the infinite loop, this makes development really hard because in the development console, while you'd try to change a style property it already renders the next frame.

Maybe it even causes performance issues but I didn't test it.

I downloaded the code and restored the state to before the update in my project and it works fine now.

About overflow

I've been trying to make a dynamic wiki that can be filled with unpredictable info, is there anyway to send the overflow from a page to the next?

Typescripts declarations missing?

This project uses typescript, yet there are no types when installing over npm. Why not?

I would gladly submit a PR to include them if allowed.

Thanks

Unable to use (in jekyll site)

Hi,

I've been trying to get it to work but I seem unable to get it to work.

I've copied the HTML and JS from the demo page.

<body>
<div class="container">
    <div>
        <button type="button" class="btn-prev">Previous page</button>
        <span class="page-current">1</span> of <span class="page-total">-</span>
        <button type="button" class="btn-next">Next page</button>
    </div>

    <div>
        State: <i class="page-state">read</i>, orientation: <i class="page-orientation">landscape</i>
    </div>
</div>

<div class="container">
    <div class="flip-book" id="demoBookExample">
        <div class="page page-cover page-cover-top" data-density="hard">
            <div class="page-content">
                <h2>BOOK TITLE</h2>
            </div>
        </div>
        <div class="page">
            <div class="page-content">
                <h2 class="page-header">Page header 1</h2>
>                 <div class="page-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In cursus mollis nibh, non convallis ex convallis eu. Suspendisse potenti. Aenean vitae pellentesque erat. Integer non tristique quam. Suspendisse rutrum, augue ac sollicitudin mollis, eros velit viverra metus, a venenatis tellus tellus id magna. Aliquam ac nulla rhoncus, accumsan eros sed, viverra enim. Pellentesque non justo vel nibh sollicitudin pharetra suscipit ut ipsum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In cursus mollis nibh, non convallis ex convallis eu. Suspendisse potenti. Aenean vitae pellentesque erat. Integer non tristique quam. Suspendisse rutrum, augue ac sollicitudin mollis, eros velit verra metus, a venenatis tellus tellus id magna.</div>
                <div class="page-footer">2</div>
            </div>
        </div>
        <!-- PAGES .... -->
        <div class="page">
            <div class="page-content">
                <h2 class="page-header">Page header - 15</h2>
>                 <div class="page-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In cursus mollis nibh, non convallis ex convallis eu. Suspendisse potenti. Aenean vitae pellentesque erat. Integer non tristique quam. Suspendisse rutrum, augue ac sollicitudin mollis, eros velit viverra metus, a venenatis tellus tellus id magna. Aliquam ac nulla rhoncus, accumsan eros sed, viverra enim. Pellentesque non justo vel nibh sollicitudin pharetra suscipit ut ipsum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In cursus mollis nibh, non convallis ex convallis eu. Suspendisse potenti. Aenean vitae pellentesque erat. Integer non tristique quam. Suspendisse rutrum, augue ac sollicitudin mollis, eros velit verra metus, a venenatis tellus tellus id magna.</div>
                <div class="page-footer">16</div>
            </div>
        </div>
        <div class="page">
            <div class="page-content">
                <h2 class="page-header">Page header - 16</h2>
>                 <div class="page-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In cursus mollis nibh, non convallis ex convallis eu. Suspendisse potenti. Aenean vitae pellentesque erat. Integer non tristique quam. Suspendisse rutrum, augue ac sollicitudin mollis, eros velit viverra metus, a venenatis tellus tellus id magna. Aliquam ac nulla rhoncus, accumsan eros sed, viverra enim. Pellentesque non justo vel nibh sollicitudin pharetra suscipit ut ipsum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In cursus mollis nibh, non convallis ex convallis eu. Suspendisse potenti. Aenean vitae pellentesque erat. Integer non tristique quam. Suspendisse rutrum, augue ac sollicitudin mollis, eros velit verra metus, a venenatis tellus tellus id magna.</div>
                <div class="page-footer">17</div>
            </div>
        </div>
        <div class="page page-cover page-cover-bottom" data-density="hard">
            <div class="page-content">
                <h2>THE END</h2>
            </div>
        </div>
    </div>
</div>

<script type="text/javascript">
  // collect all the trips
  var trips = document.getElementsByClassName("trip");
  // get window width and height
  var winWidth = window.innerWidth;
  var winHeight = window.innerHeight;

  // i stands for "index". you could also call this banana or haircut. it's a variable
  for ( var i=0; i < trips.length; i++ ) {
    
      // shortcut! the current div in the list
      var thisTrip = trips[i];
      
      // get random numbers for each element
      randomTop = getRandomNumber(0, winHeight - 200);
      randomLeft = getRandomNumber(0, winWidth - 200);
      randomRotate = getRandomNumber(0, 1);
      
      // update top and left position
      thisTrip.style.top = randomTop +"px";
      thisTrip.style.left = randomLeft +"px";
      thisTrip.style.transform = "rotate(" + randomRotate +"turn)";
      
  }

  // function that returns a random number between a min and max
  function getRandomNumber(min, max) {
    return Math.random() * (max - min) + min;
  }
</script>

<script type="text/javascript" src="assets/js/page-flip.browser.js"></script>
<script type="module">
	import {PageFlip} from 'page-flip';

	document.addEventListener('DOMContentLoaded', function() {

	    const pageFlip = new PageFlip(
	        document.getElementById("demoBookExample"),
	        {
	            width: 550, // base page width
	            height: 733, // base page height

	            size: "stretch",
	            // set threshold values:
	            minWidth: 315,
	            maxWidth: 1000,
	            minHeight: 420,
	            maxHeight: 1350,

	            maxShadowOpacity: 0.5, // Half shadow intensity
	            showCover: true,
	            mobileScrollSupport: false // disable content scrolling on mobile devices
	        }
	    );

	    // load pages
	    pageFlip.loadFromHTML(document.querySelectorAll(".page"));

	    document.querySelector(".page-total").innerText = pageFlip.getPageCount();
	    document.querySelector(
	        ".page-orientation"
	    ).innerText = pageFlip.getOrientation();

	    document.querySelector(".btn-prev").addEventListener("click", () => {
	        pageFlip.flipPrev(); // Turn to the previous page (with animation)
	    });

	    document.querySelector(".btn-next").addEventListener("click", () => {
	        pageFlip.flipNext(); // Turn to the next page (with animation)
	    });

	    // triggered by page turning
	    pageFlip.on("flip", (e) => {
	        document.querySelector(".page-current").innerText = e.data + 1;
	    });

	    // triggered when the state of the book changes
	    pageFlip.on("changeState", (e) => {
	        document.querySelector(".page-state").innerText = e.data;
	    });

	    // triggered when page orientation changes
	    pageFlip.on("changeOrientation", (e) => {
	        document.querySelector(".page-orientation").innerText = e.data;
	    });
	});
</script>
</body>

I got an error saying:
Uncaught TypeError: Failed to resolve module specifier "page-flip". Relative references must start with either "/", "./", or "../".

So I changed the first line of the script to:
import {PageFlip} from './assets/js/page-flip.browser.js';
To locate the actual script.

And then I get:
Uncaught SyntaxError: The requested module './assets/js/page-flip.browser.js' does not provide an export named 'PageFlip' (at (index):125:10)

What am I missing?

Thanks a lot in advance.

Demo: Performance issue in Firefox

Hi, I'm using Firefox Dev.

I noticed that it performs very smoothly but after a few seconds (even without interaction after page loads) The flip animation becomes slow and laggy.

I also noticed that if I only Ctrl+zoom (I mean changing the zoom level that way) the problem is solved but again happens after a few seconds.
This doesn't happen in Edge.
Not sure if it's a Firefox issue. but sounds like it's a rendering problem.

Thanks.

Book stops working after more than 40 pages

Like title says book gives a "Uncaught TypeError: Cannot read property 'classList' of null" error when you add more than 40 pages.

edit: So turns out my page was running the pageflip code before fully loading the content. Fixed that on my end. sry. You can delete this issue

Disable swipe to flip

Hi
I'm trying to integrate zoomist and, when the page is zoomed, the swipe to turn the page effect makes impossible to move the zoomed image to another part of it

Is it possible to disable the swipe event?
Is it possible to limit the flip event to only click in the corners?

Thanks

Prevent Click Any Position To Trigger Turn Page Event

Is it possible to modify that won't trigger turn event when clicking anywhere in the book?
for example: Turn page when only click corner, draw or double click?
I see that there is a config value call disableFlipByClick, but it doesn't work.

Auto scroll on page flip for mobile view

When I use mobile view, or mobile apps to view the result. On page flip from second to third page ( One page is visible on the screen. for mobile view) the webpage scrolls up.

flipNext() and flip(to_page) don't work when disableFlipByClick is true

When disableByFlipClick is true, flipNext() has no effect; and flipToPage(pagenum) does nothing when the pagenum > currentpage.

Why? Because at line 245 of Flip.ts, the flipNext method simulates a lick at the right edge (top or bottom) of the displayRect and calls .flip(). But at line 80 of Flip.ts, only when disableFlipByClick is true, there is a test to see if the point passed in is within the display bounds; which fails because the x value is NOT strictly less than the displayWidth (it's equal to it).

I don't have the rig set up to recompile and test TypeScript so I won't post a pull request, but the fix is to edit line 245 of Flip.ts so that the x value passed in is a few pxiels less than the displayWidth; e.g. edit line 245 of Flip.ts to read:

x: this.render.getRect().left + this.render.getRect().pageWidth * 2 - 10,

and that fixes both flipNext() and flipToPage. (In my case, I just monkey-patched it.) Hope that helps!

Unable to have soft cover like newspaper

Hi all,

I would like to have soft covers like newspaper. Even if I add data-density="soft" to my divs, The covers are always hard.

<div class="flip-book" id="example">
  <div class="page page-cover page-cover-top" data-density="soft">
    <div class="page-content">
      <h2>BOOK TITLE</h2>
    </div>
  </div>
  <div class="page">
    <div class="page-content">
      <h2 class="page-header">Page Header 1</h2>
      <div class="page-image" style="background-image: url(1.jpg)"></div>
   </div>
  </div>
   ...
  <div class="page page-cover page-cover-bottom" data-density="soft">
    <div class="page-content">
      <h2>THE END</h2>
    </div>
  </div>
</div>

Could you please tell me how to have soft covers?

Thank you.

shadow doms are lost after updateFromHtml

For some reasons, I have to dynamically fetch the page data and update the view. I used the updateFromHTML method, the page doms are added while the shadow doms are lost.

Implementation Question

Hi,

I am trying to build a book with multiple artworks, but I am building it with Konvajs and React. So essentially a page right now is a canvas. All of the details of each page are Konva node which is just canvas element.

When I try to put together with StPageFlip, I think there is too many canvas on the screen as each page is a canvas itself. I was following your tutorial on React forward Ref

import { Stage } from "react-konva";
const Page = (forwardRef) => { 
    return <Stage> </Stage>  <= this is a canvas
}
<PageFlip>
   <Page> => if I construct more that 10 page, this is extremely slow
<PageFlip />

Can you give me some pointer, on how to reuse a book flip to pass dynamic content, and how to tell the book that there is only two pages

 <PageFlip> 
   <Page currentLeft>
    <Page currentRight> 
    <Page nextLeft>
    <Page nextRight> 
<PageFlip />

I think that minimal set up is doable, as I can change the data of the Page dynamically when the user flip.
Also if you have suggestions on rendering a canvas within a canvas is ideal, it is very CPU intensive.

Anyway to accomplish a dog ear effect?

This package is a life saver, thanks!

I'm wondering if there might be a way to create a dog ear effect (to give a visual indicator that the page can be flipped (for my needs, I only really need the ability to fold the upper right corner)).

Multiple pages flip / fold effect

If you navigate really fast using the next and prev buttons on the demo, you can see the animation is interrupted every time.
Will be nice if a new flip effect / animation is created for each page without destroying the first one.

Here is an example of this:
https://fliphtml5.com/gtms/smlk

Remove shadow

How remove shadow in the left side of book?
btw i'm using "loadFromImages" method, so pageflip draw in canvas.

Screenshot_4

Клонирование, маусэвенты

Приветствую. Есть пара моментов.
Я делаю что-то вроде фотоальбома, который заполняет пользователь своими фотографиями. Захотелось прикрутить смену разворотов перелистыванием страниц. Я попробовал вашу библиотеку и столкнулся с некоторыми проблемами.
У меня страница это дивка с канвасом, с которым надо взаимодействовать. При инициализации или окончании анимации у вас, для отображения текущего разворота, используются клонированные элементы. Я так понял, при клонировании канваса его содержимое не переносится. В общем, получаются пустые страницы. Я удалил клонирование из js и вроде все работает хорошо, я не увидел разницы.
Второй момент, нельзя отключить перелистывание с использованием мыши. То бишь, сделать так, чтобы можно было листать только по кнопкам где-нибудь внизу, а мышкой работать с моими канвасами:) Опять пришлось вручную удалять маусевенты.
С клонированием не знаю как правильно, но настройку для отключения маусэвентов можно прикрутить, думаю;)

Preload strategy

Hi,
have any chance to have a preload strategy to fast load with high numbers of pages?

Thanks

Prevent page turn & animation?

Hi,

I am using this library to create an interactive book that contains videos/links on the page. When clicking the controls in the video, or links on the page, it causes the page to turn. Is there any way I can prevent this event from triggering, when clicking a certain component with a specific className?

Fire a onInit event on first load #FeatureRequest

Hello,
I need to display additional data around my flipbook depending on the active page so I need to know which page is active, and if it has been loaded on landscape or portrait mode. Therefore, firing a "onInit" event on first load would be great.

Thank you

Zoom support on touch devices (pinch-to-resize or css transform)

Hi,
I'm using this in a side project and I'm very happy with it :)

I have a feature request: I would really like to be able to zoom. I don't particularly care if that would be viewport resizing (which your event handlers currently prevent), or css transforms like e.g. https://react-quick-pinch-zoom.netlify.app/ uses.
I am happy to help with the solution, in fact I already tried, but I don't have any experience working directly with mouse/touch events.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.