React-Native,在 Webview 中渲染 H5 Canvas 和 EaselJS 形状

Posted

技术标签:

【中文标题】React-Native,在 Webview 中渲染 H5 Canvas 和 EaselJS 形状【英文标题】:React-Native, Render H5 Canvas and EaselJS shapes in Webview 【发布时间】:2017-11-08 23:31:06 【问题描述】:

我创建了一个可以使用 Canvas 和 EaselJS 绘制的 html 页面,我可以在 Web 应用程序中使用鼠标在画布中绘制。另外,我想将页面嵌入到 React-native Webview 中。

ios 中,它嵌入到 Webview 中成功,但是,不能用手指触摸绘图。我找不到原因并想办法解决它。

在网络浏览器中:

See html in browser(picture)

在 iOS 应用程序中,它可以在 Webview 中呈现,但不能使用笔触摸绘图。

下面的HTML代码(我已经添加了触摸事件监听):

<!DOCTYPE html>
<html>

<head>
    <title></title>

    <script type="text/javascript" src="easeljs/utils/UID.js"></script>
    <script type="text/javascript" src="easeljs/events/EventDispatcher.js"></script>
    <script type="text/javascript" src="easeljs/events/MouseEvent.js"></script>
    <script type="text/javascript" src="easeljs/geom/Matrix2D.js"></script>
    <script type="text/javascript" src="easeljs/geom/Rectangle.js"></script>
    <script type="text/javascript" src="easeljs/filters/Filter.js"></script>
    <script type="text/javascript" src="easeljs/filters/BoxBlurFilter.js"></script>
    <script type="text/javascript" src="easeljs/display/DisplayObject.js"></script>
    <script type="text/javascript" src="easeljs/display/Container.js"></script>
    <script type="text/javascript" src="easeljs/display/Text.js"></script>
    <script type="text/javascript" src="easeljs/display/Graphics.js"></script>
    <script type="text/javascript" src="easeljs/display/Shape.js"></script>
    <script type="text/javascript" src="easeljs/display/Stage.js"></script>
    <script src="https://code.jquery.com/jquery-3.2.1.slim.js" integrity="sha256-tA8y0XqiwnpwmOIl3SGAcFl2RvxHjA8qp0+1uCGmRmg=" crossorigin="anonymous"></script>

    <script type="text/javascript">
        var canvas, stage, ctx;
        var tooltype = '';

        //Use draw|erase
        use_tool = function(tool) 
            tooltype = tool; //update
        

        function free_hand_draw() 
            //Variables
            var canvasx = $(canvas).offset().left;
            var canvasy = $(canvas).offset().top;
            var last_mousex = last_mousey = 0;
            var mousex = mousey = 0;
            var mousedown = false;

            //Mousedown
            start = function(e) 
                last_mousex = mousex = parseInt(e.clientX - canvasx);
                last_mousey = mousey = parseInt(e.clientY - canvasy);
                mousedown = true;
            ;
            $(canvas).on('mousedown', start);
            $(canvas).on('touchstart', start);

            //Mouseup
            end = function(e) 
                mousedown = false;
            ;
            $(canvas).on('mouseup', end);
            $(canvas).on('touchend', end);

            //Mousemove
            move = function(e) 
                mousex = parseInt(e.clientX - canvasx);
                mousey = parseInt(e.clientY - canvasy);
                if (mousedown) 
                    var shape = new createjs.Shape();
                    if (tooltype == 'draw') 
                        shape.graphics.beginStroke("black").setStrokeStyle(2, 'round').moveTo(last_mousex, last_mousey).lineTo(mousex, mousey);
                        stage.addChild(shape);
                        stage.update();
                     else if (tooltype == 'erase') 
                        shape.graphics.beginStroke("white").setStrokeStyle(10, 'round').moveTo(last_mousex, last_mousey).lineTo(mousex, mousey);
                        stage.addChild(shape);
                        stage.update();
                    
                
                last_mousex = mousex;
                last_mousey = mousey;
            ;
            $(canvas).on('mousemove', move);
            $(canvas).on('touchmove', move);
        

        function createShape(type, value = '') 
            var shape = new createjs.Shape();
            switch (type) 
                case 'circle':
                    shape.graphics.beginStroke("black").drawCircle(0, 0, 50);
                    shape.x = 100;
                    shape.y = 100;
                    stage.addChild(shape);
                    break;
                case 'line':
                    shape.graphics.beginStroke("black").setStrokeStyle(10, 'round').moveTo(30, 30).lineTo(90, 90);
                    shape.x = 20;
                    shape.y = 20;
                    stage.addChild(shape);
                    break;
                case 'rect':
                    shape.graphics.beginStroke("black").drawRect(0, 0, 50, 50);
                    shape.x = 70;
                    shape.y = 70;
                    stage.addChild(shape);
                    break;
                case 'text':
                    var text = new createjs.Text(value, "20px Arial", "#ff7700");
                    text.x = 20;
                    stage.addChild(text);
                    document.getElementById('input_text').value = '';
                    break;
                case 'pen':
                    use_tool('draw');
                    break;
                case 'erase':
                    use_tool('erase');
                    break;
            
            stage.update();
        

        function getText() 
            return document.getElementById('input_text').value
        

        function init() 
            if (canvas) 
                document.removeChild(canvas);
            

            canvas = document.createElement('canvas');
            canvas.width = 300;
            canvas.height = 300;

            var parent = document.getElementById('canvas');
            parent.appendChild(canvas);

            ctx = canvas.getContext('2d');
            stage = new createjs.Stage(canvas);
            free_hand_draw();
        
    </script>
</head>

<body onload="init();">
    <div style="display: block; width: 300px;">
        <div id="canvas" style="float: left; padding-right: 20px;"></div>

        <input type="button" id="circle" value="Add Circle">
        <input type="button" value="Add Square" onclick="createShape('rect');">
        <input type="button" value="Add Line" onclick="createShape('line');">
        <input type="button" id="pen" value="Use Pen">
        <input type="button" value="Erase" onclick="createShape('erase');">
        <input type="text" id="input_text">
        <input type="button" value="Input text" onclick="createShape('text', getText());">
    </div>
</body>

</html>

React 原生代码 sn-p 是:

render() 
              return (
                <View style=styles.container>
                  <WebView source= 
                Platform.OS === 'ios' ?       require('../../server/public/index.html') : uri: 'file:///android_asset/index.html'
                  javaScriptEnabled=true
                  ref=c =>  this.webview = c; 
                  onLoad=this.injectJavaScript
                  startInLoadingState=true
                  mediaPlaybackRequiresUserAction=true
                  scrollEnabled= this.props.scrollEnabled || false  />
                </View>
              )
            

可以在舞台上创建形状,不能用手指触摸绘图!

See html in iOS emulator(picture)

同时,HTML页面在iOS中渲染成功,但是无法加载html中的js代码和js引用链接。 就像 React-native 中的 issue 8089 / 505。

有什么帮助吗?

谢谢。

【问题讨论】:

【参考方案1】:

您应该添加代码以启用触摸事件。添加以下代码以启用它

 createjs.Touch.enable(stage);

更多信息请参考以下文档 http://www.createjs.com/docs/easeljs/classes/Touch.html

【讨论】:

以上是关于React-Native,在 Webview 中渲染 H5 Canvas 和 EaselJS 形状的主要内容,如果未能解决你的问题,请参考以下文章

脚本在 WebView 中不适用于 react-native

如何在 react-native 中为 webView 请求设置自定义标头

如何在 WebView [React-Native] 中禁用用户文本选择

React-Native,在 Webview 中渲染 H5 Canvas 和 EaselJS 形状

如何在没有 webview 的情况下将 vimeo 播放器嵌入 react-native?

当设备在 react-native 中离线时,在 webview 中显示本地图像