• 【Azure Developer】App Service + PubSub +JS 实现多人版黑客帝国文字流效果图


    需要描述

    1)实现黑客帝国文字流效果图,JS功能

    2)部署在云中,让大家都可以访问,App Service实现

    3)大家都能发送消息,并显示在文字流中,PubSub(websocket)实现

    终极效果显示:

    执行步骤

    1)在 Azure 中创建 App Service 服务,参考官方文档:快速入门:部署 ASP.NET Web 应用

    Azure门户中创建App Service的动画演示:

    2)在 Azure 中创建 PubSub 服务,参考官方文档:快速入门:从 Azure 门户创建 Web PubSub 实例

    Azure门户中创建Web PubSub的动画演示:

     

    3)使用Visual Studio 2022创建一个.NET 6.0 Web项目,参考PubSub的文档来创建一个服务端来托管 /negotiate API和Web 页面,参考示例:教程:使用子协议在 WebSocket 客户端之间发布和订阅消息

    Program.cs文件内容为:

    • string ConnectionString = "<Web PubSub Access Key>" 获取的办法见第二步创建的PubSub服务的Key页面 --> Connection String

    using Azure.Messaging.WebPubSub;
    using Microsoft.Extensions.Azure;
    
    string ConnectionString = "<Web PubSub Access Key>";
    
    // Add WebPubSub Service 
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddAzureClients(builder =>
    {
        builder.AddWebPubSubServiceClient(ConnectionString, "stream");
    });
    
    var app = builder.Build();
    
    app.UseStaticFiles();
    
    app.UseRouting();
    
    //实现生产客户端WebSocket SAS URL
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGet("/negotiate/{userid}", async (string userid, HttpContext context) =>
        {
            var service = context.RequestServices.GetRequiredService<WebPubSubServiceClient>();
            var response = new
            {
                url = service.GetClientAccessUri(userId: userid, roles: new string[] { "webpubsub.sendToGroup.stream", "webpubsub.joinLeaveGroup.stream" }).AbsoluteUri
            };
            await context.Response.WriteAsJsonAsync(response);
        });
    });
    
    app.MapGet("/", () => "/index.html");
    
    app.Run();

    前端 wwwroot/stream.html 内容为:

    <html>
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
            background-color: rgb(0, 0, 0);
        }
    
        #divList {
            width: 98%;
            height: 79%;
            border: solid 1px rgb(0, 15, 0);
            ;
            margin: 0px auto;
            overflow: hidden;
            position: relative;
        }
    
        .divText {
            position: absolute;
        }
    
        .divText span {
            display: block;
            font-weight: bold;
            font-family: Courier New;
        }
    </style>
    <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
    
    <body> <br>
        <h2 style="text-align:center; color:white;">STREAM BOARDCAST (<span id="spanCount">0</span>)</h2>
        <div id="divList">
        </div>
        <h3 style="text-align:left; color:grey;">Send</h3>
        <div style=" margin: 5px 15px;">
            <input id="inputmessage" style="text-align:left; color:green;  86%; height: 55px; font-size: 40px;" onsubmit="sendmessage()"><button
                style="text-align:center; color:green;  12%; height: 55px;font-size: 40px;" onclick="sendmessage()">Send</button>
        </div>
        <div style="display:none;">
            <h1>Message</h1>
            <div id="output"></div>
            <br>
            <h1>Message</h1>
            <div id="outputmsg"></div>
        </div>
        <script>
            var textarray = ["Hello Mooncake,Welcome to use PubSub", "Who are you? Put your PIN ... "];
            var wsurl = "";
            var wsclient;
            let ackId = 0;
            (async function () {
                let res = await fetch('/negotiate/client_2')
                let data = await res.json();
                wsurl = data.url;
                let ws = new WebSocket(data.url, 'json.webpubsub.azure.v1');
                ws.onopen = () => {
                    console.log('connected');
                };
    
                let output = document.querySelector('#output');
                let outputmsg = document.querySelector('#outputmsg');
    
                ws.onmessage = event => {
                    let d = document.createElement('p');
                    d.innerText = event.data;
                    output.appendChild(d);
    
                    let message = JSON.parse(event.data);
                    if (message.type === 'message' && message.group === 'stream') {
                        let d = document.createElement('span');
                        d.innerText = message.data;
                        textarray.push(message.data);
                        outputmsg.appendChild(d);
                        window.scrollTo(0, document.body.scrollHeight);
                    }
                };
    
                ws.onopen = () => {
                    console.log('connected');
                    ws.send(JSON.stringify({
                        type: 'joinGroup',
                        group: 'stream',
                        ackId: ++ackId
                    }));
    
                    wsclient = ws;
                };
            })();
    
    
            function sendmessage() {
    
                if (wsclient.readyStatue == WebSocket.OPEN) {
                    wsclient.send(JSON.stringify(
                        {
                            type: "sendToGroup",
                            group: "stream",
                            data: $('#inputmessage').val(),
                            ackId: ++ackId // ackId is optional, use ackId to make sure this action is executed
                        }
                    ));
                }
                else { 
                    wsclient = new WebSocket(wsurl, 'json.webpubsub.azure.v1');
    
                    wsclient.onopen = () => {
                        console.log('connected again');
                        wsclient.send(JSON.stringify({
                            type: "sendToGroup",
                            group: "stream",
                            data: $('#inputmessage').val(),
                            ackId: ++ackId
                        }));
     
                    };
                }
                $('#inputmessage').focus();
            }
    
    
    
            function rand(min, max) {
                return min + Math.round(Math.random() * (max - min));
            }
    
            function add(message) {
                var maxwdth = $('#divList').width();
                var x = rand(0, maxwdth);
                var html = '<div class="divText" style="left:' + x + 'px; bottom:500px;">';
    
                var color = [];
                for (var i = 1; i < message.length; i++) {
                    var f = i.toString(16);
                    color.push('0' + f + '0');
                }
    
                var fontSize = rand(20, 36);
                for (var i = 1; i <= message.length; i++) {
                    var c = message[i - 1];
                    html += '<span class="s' + i + '" style="color:#' + color[i - 1] + '; font-size:' + fontSize + 'px; text-shadow:0px 0px 10px #' + color[i - 1] + ';">' + c + '</span>';
                }
                html += '</div>';
                $('#divList').append(html);
            }
    
            function run() {
                var x = rand(0, 100);
                if (x < 100) {
                    var lgh = textarray.length;
                    if (textarray.length > x) add(textarray[x]);
                    else
                        add(textarray[x % lgh]);
                }
                $('#spanCount').html($('.divText').size());
    
                $('.divText').each(function () {
                    var y = $(this).css('bottom');
                    y = parseInt(y);
                    y -= $(this).find('span').eq(0).height();
                    $(this).css('bottom', '' + y + 'px');
                    if (y + $(this).height() <= 0) {
                        $(this).remove();
                        return;
                    }
                });
    
                window.setTimeout(run, 200);
            }
            run();
    
        </script>
    </body>
    
    </html>

    项目结构示意图:

    项目创建完成后,可以在本机进行调试。正常运行后即可发布到Azure App Service上。因代码简单并且可读性强,可自行理解。

    4)通过VS 2022发布到App Service中

    VS 2022 通过Publish Profile 发布站点演示动画:

    发布版本操作完成。

    附录一:本地黑客帝国文字流效果,可自行输入即修改内容版

    复制内容,直接保存在本地文件中,文件命名为 localstream.html后使用浏览器打开即可

    <html>
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
            background-color: rgb(0, 0, 0);
        }
    
        #divList {
            width: 98%;
            height: 79%;
            border: solid 1px rgb(0, 15, 0);
            ;
            margin: 0px auto;
            overflow: hidden;
            position: relative;
        }
    
        .divText {
            position: absolute;
        }
    
        .divText span {
            display: block;
            font-weight: bold;
            font-family: Courier New;
        }
    </style>
    <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
    
    <body> <br>
        <h2 style="text-align:center; color:white;">STREAM BOARDCAST (<span id="spanCount">0</span>)</h2>
        <div id="divList">
        </div>
        <h3 style="text-align:left; color:grey;">Send</h3>
        <div style=" margin: 5px 15px;">
            <input id="inputmessage" style="text-align:left; color:green;  86%; height: 55px; font-size: 40px;" onsubmit="sendmessage()"><button
                style="text-align:center; color:green;  12%; height: 55px;font-size: 40px;" onclick="sendmessage()">Send</button>
        </div>
        <div style="display:none;">
            <h1>Message</h1>
            <div id="output"></div>
            <br>
            <h1>Message</h1>
            <div id="outputmsg"></div>
        </div>
        <script>
            var textarray = ["Hello Mooncake,Welcome to use PubSub", "Who are you? Put your PIN ... "];
    
            function sendmessage() {
                textarray.push($('#inputmessage').val());
                $('#inputmessage').focus();
            }
    
    
    
            function rand(min, max) {
                return min + Math.round(Math.random() * (max - min));
            }
    
            function add(message) {
                var maxwdth = $('#divList').width();
                var x = rand(0, maxwdth);
                var html = '<div class="divText" style="left:' + x + 'px; bottom:500px;">';
    
                var color = [];
                for (var i = 1; i < message.length; i++) {
                    var f = i.toString(16);
                    color.push('0' + f + '0');
                }
    
                var fontSize = rand(20, 36);
                for (var i = 1; i <= message.length; i++) {
                    var c = message[i - 1];
                    html += '<span class="s' + i + '" style="color:#' + color[i - 1] + '; font-size:' + fontSize + 'px; text-shadow:0px 0px 10px #' + color[i - 1] + ';">' + c + '</span>';
                }
                html += '</div>';
                $('#divList').append(html);
            }
    
            function run() {
                var x = rand(0, 100);
                if (x < 100) {
                    var lgh = textarray.length;
                    if (textarray.length > x) add(textarray[x]);
                    else
                        add(textarray[x % lgh]);
                }
                $('#spanCount').html($('.divText').size());
    
                $('.divText').each(function () {
                    var y = $(this).css('bottom');
                    y = parseInt(y);
                    y -= $(this).find('span').eq(0).height();
                    $(this).css('bottom', '' + y + 'px');
                    if (y + $(this).height() <= 0) {
                        $(this).remove();
                        return;
                    }
                });
    
                window.setTimeout(run, 200);
            }
            run();
    
        </script>
    </body>
    
    </html>

    PS: 与PubSub版本相比,只是移除了WebSocket的相关代码

    运行效果

    参考资料

    JS 黑客帝国文字下落效果: https://www.cnblogs.com/zjfree/p/3833592.html 

    教程:使用子协议在 WebSocket 客户端之间发布和订阅消息:https://docs.microsoft.com/zh-cn/azure/azure-web-pubsub/tutorial-subprotocol?tabs=csharp#using-a-subprotocol

    快速入门:部署 ASP.NET Web 应用:https://docs.azure.cn/zh-cn/app-service/quickstart-dotnetcore?tabs=net60&pivots=development-environment-vs

  • 相关阅读:
    脑子好,蹦两下!程序员应该玩的小游戏
    推荐博客备份软件blog_bakcup
    经验(转)
    as super
    ActionScript工程如何使用Flash CS的fl包中的UI组件(转)
    astar(转)
    GROUPING,ROLLUP和CUBE(转)
    什么是分区表?为什么要用分区表?如何创建分区表?
    Flash player 详解(zhuan)
    jsfl(转)
  • 原文地址:https://www.cnblogs.com/lulight/p/16320123.html
Copyright © 2020-2023  润新知