Code Monkey home page Code Monkey logo

elm-canvas's Introduction

🚨🚨THIS IS EXPERIMENTAL.🚨🚨

We are trying to make this package reliable, and for all we know it is, but we havent used it nearly enough to know for sure. Use are your own risk. If you do discover problems please let us know, it would be really useful.

Canvas for Elm

Making the canvas API accessible within Elm. The canvas element is a very simple way to render 2D graphics.

Whats this all this about?

This code ..

import Html exposing (Html)
import Canvas exposing (Size, Point, Canvas, DrawOp(..))
import Color

main : Html a
main =
    Canvas.toHtml [] blueRectangle


blueRectangle : Canvas
blueRectangle =
    let
        size : Size
        size =
            { width = 400
            , height =  300
            }
    in
        Canvas.initialize size
            |> Canvas.draw (fillBlue size)


fillBlue : Size -> DrawOp
fillBlue size =
    [ FillStyle Color.blue
    , FillRect (Point 0 0) size
    ]
        |> Canvas.batch


-- Canvas.batch : List DrawOp -> DrawOp
-- Canvas.draw : DrawOp -> Canvas -> Canvas
-- Canvas.toHtml : List (Attribute a) -> Canvas -> Html a

.. renders as ..

alt text

The Elm-Canvas library provides the type Canvas, which can be passed around, modified, drawn on, pasted, and ultimately passed into toHtml where they are rendered.

Almost all the properties and methods of the 2d canvas context are available in Elm-Canvas. Understanding them is necessary for full useage of this package.

What is the Canvas Element?

The mozilla developer network has the best answer to this question. But basically, the canvas element is a unique html element that contains something called image data. The canvas element renders its image data, and by modification of its image data you can change what is rendered. This library provides an API to modify and set canvas image data.

When should you use Elm-Canvas?

We made this package for a some really unusual use cases, which likely arent your use case. Think hard before choosing to use Elm-Canvas, you probably dont need it. If you have image assets you want to move around the screen (like in a video game), then evancz/elm-graphics and elm-community/webgl are better options. If you want to render vector graphics use elm-svg. You should use the canvas when you absolutely need to change pixel values in a very low level way, which is an unusual project requirement.

In making this package, we had various design considerations. On one hand we wanted to make things clearer and simpler than the native canvas API actually is (theres a lot of room for improvement on that front). On the other hand, the use cases we had in mind for Elm-Canvas are some what broad. For Elm-Canvas, we are just trying to expose as much of the native canvas API as we can into Elm. Elm-Canvas makes no presumption about a what your specific use case is, but we figure direct access to the canvas api will help you get to where you need.

Contributing

Pull requests, and general feedback welcome. I am in the #canvas channel in the Elm Slack.

Thanks

Thanks to Alex for contributing to this project, but also for his feedback and insights into what an Elm canvas API needs to look like, which have been instrumental in the development of Elm-Canvas. Thanks to the authors of the Elm Web-Gl package for writing really readable code, which I found very educational on how to make native Elm packages. Thanks to all the helpful and insightful people in the Elm slack channel, including Alex Spurling, the maker of this elm app called 'quick draw'. Thanks to mdgriffin, Noah Gordon, and all the other nice people at the Elm NYC meet up who had great feedback for this project..

How to use Elm-Canvas in your project

Elm-Canvas is a native module, which means you cant install it from package.elm-lang.org. You can still use this module in your project, but it will take a little work. One way to install it, is to use elm-github-install. You can do it manually too, like this..

0 Download either this repo, or better yet, one of the tagged releases (like 0.1.0).

1 Copy the content of ./src into the source directory of your project. So that means copying ./src/Canvas.elm and ./src/Native/ to the same directory as your Main.elm file.

2 Open up Native/Canvas.js. The first line says var _elm_canvas$elm_canvas$Native_Canvas = function () {. In your elm-package.json file, you have a repo field. In that first line of Native/Canvas.js, replace the first elm_canvas with the user name from the elm-package.jsons repo, and replace the second elm_canvas with the project name in your repo field. So if your elm package lists "repository": "https://github.com/ludwig/art-project.git", change the first line of Native/Canvas.js to var _ludwig$art_project$Native_Canvas = function () {.

3 Add the line "native-modules": true, to your elm package file.

License

The source code for this package is released under the terms of the BSD3 license. See the LICENSE file.

elm-canvas's People

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

Watchers

 avatar  avatar  avatar  avatar  avatar

elm-canvas's Issues

Change batch type signature

Batch currently is List DrawOp -> Canvas -> Canvas, but based off feedback, this is a confusing and unexpected type signature. Cmd.batch and Sub.batch both have the type signature List a -> a, so Canvas.batch should too. To apply a DrawOp, we should make a function like draw : DrawOp -> Canvas -> Canvas

no requestAnimationFrame example

To optimize the rendering of a frequently update canvas, requestAnimationFrame should be used, but there is no example of how to do this (and there should be).

Setting pixel data may not always do the right thing

This is a bit of a mix of an issue and a question. I'm building some basic photo editing, and canvas is obviously a good fit for this in elm/the web. My design relies on me being able to draw on top of an image to show crop/selection regions. With the current implementation, it appears you're copying/drawing by setting pixels on the canvas - is there a good reason for this? This prevents me from drawing transparencies on the image, and seems inefficient for most drawing operations. I get that pixel operations are basically the lowest primitive we can get, but why not leverage more of the native functions? I haven't done any benchmarking, so I don't know if there are any performance benefits, but I'd think it would at least be on par with your current by-pixel implementation, with the added bonus of being able to draw on top of images with transparency.

Locally, I'm working on an implementation that I've described using more canvas 2d methods, and I'd be happy to refactor it and write a PR for you if you're interested.

New Function : Scale

Take the existing pixel data, and scale it

scaleX : Float -> Canvas -> Canvas

scaleY : Float -> Canvas -> Canvas

scale : Float -> Canvas -> Canvas
scale f = scaleX f >> scaleY f

Elm 0.19 - No more Native support

Since 0.19 the ability to freely use native modules has been removed.
Apparently projects in Elm Explorations are allowed to use native code.

My question is: Is there a plan to move this canvas project to elm explorations?

At the moment I use elm-canvas as the render for my little pixel game and I need to know if I should change to webgl or if there is a future in the library.

Maybe there is a way for me to help?

Another example :)

Hey!

Thanks for the project! Just wanted to let you know that I've borrowed the code to create another example (still WIP but) here

Cheers!

CanvasData type

Its really performant to turn canvas data into a 2D JavaScript array of rows and columns of pixels. Its unfortunately less performant to turn a 2D JavaScript array into an Elm list or a JavaScript list.

Perhaps there could be type CanvasData. and functions like `transform : Position -> (Color -> Color)

transformPixel : Position -> (Color -> Color) -> CanvasData

fromData : CanvasData -> Size -> Canvas

type alias Color = (Int, Int, Int, Int)

Eliminate type Image

Image is only used for drawing onto a canvas. Images should therefore be loaded in as type Canvas for simplicity.

Elm-Canvas references document, and in some contexts that doesnt exist

I was using Elm-Canvas in a project, when Elm-css started erroring with "document is not defined". My work around was adding this code:

var fakeDoc = { 
  createElement: function(){ 
    return { 
      getContext: function() {
        return {
          drawImage: function(){},
          beginPath: function(){},
          rect: function(){},
          fill: function(){},
        }
      } 
    }; 
  }
};

var D = typeof document === "undefined" ? fakeDoc : document; 

Idea : Remove Pixel sub module

I really need the pixel sub module for my own project, but its kind of out of the scope of elm-canvas. Maybe it should go into its own repo.

Furthermore, maybe it can get broken down further. We could make a repo called something like elm-canvas/raster-shapes, which contains all the pixel perfect line calculation stuff, and we can even publish it. And elm-canvas/pixel for pixel drawing that uses elm-canvas/raster-shapes.

Using v1.0.0, import Canvas exposing (Size) fails.

I'm using elm-git-install, and my dependency set to: "elm-community/canvas": "1.0.0 <= v < 2.0.0". In master, I see Size being exposed in Canvas.elm, but locally in my elm-stuff/packages directory, Size is not being exposed properly. I'm not sure if for some reason I have the wrong version number (which seems contrary to you elm-package.json file), or if elm-git-install is backing onto the elm package website and there is a sync issue, or if for some reason elm-git-install is pointing at the wrong ref in your repo.

toDataUrl union type to represent encoding

toDataUrl takes a string and a float, but the string and float represent the encoding, and the quality level. Some encodings dont have quality levels. Maybe..

type Encoding
    | Png
    | Jpeg Float

New function : getPixel

this package needs a function that returns the color of a specific pixel in a Canvas

getPixel : Position -> Canvas -> Color

Idea : Get rid of Point submodule

We made the point submodule because some times you want to specify stuff in terms of Float and get anti aliased edges, and other times you want things to be really exact about each pixel so you should use Int. I think this was kind of over engineered, and it doesnt fully address the concern, for example a canvas that is 199 pixels wide internally, and 200 pixels wide externally will be anti aliased no matter what.

I propose switching from Point -> ... typing to Float -> Float -> ... typing. The pixel perfect question can be handled else where.

New functions : setTransparency and adjustTransparency

Functions to set the transparency of every pixel in a canvas, and to multiply the transparency of every pixel in the canvas.

setTransparency : Float -> Canvas -> Canvas
adjustTransparency : Float -> Canvas -> Canvas

In set, the transparency is simple set to the input Float, in adjustthe transparency is set to the existing transparency times the inputFloat`.

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.