SOURCE

console 命令行工具 X clear

                    
>
console
var userIdArr = ["mikulu777", "failverde", "chiao622", "rubychaoo", "minerva8018", "CinCinBear", "missypwns", "ChloeLock", "sweet0313love", "AimzAtchu", "Alliestrasza", "winny3531", "AlexiaRaye", "ning886", "mini8816", "yuanyuan_satomi", "blair0823", "deathfong", "vanessa_cc", "aphrolin1107", "iris522", "aga191919", "tsukilin", "donbingweihan", "zxcv323215", "n00biesuzikinz", "kana000089", "fanvivi", "lulalalulula", "midahri", "danenebobar", "Adobe", "mikadaime", "Ms_Vixen", "soming1907", "freecodecamp", "Rakin", "gmdkdsla", "fluidwindlolz", "LukiLuluped", "tim885885", "OGN_LoL", "LCK1", "chery0505", "VeRsuta", "ESL_SC2", "SaltyBet", "ryo_0814", "dnrkdnjs", "TwitchShow"];
var strGame,
    strView,
    strLink,
    strInfo;
var noLogo = "twitch/img/nologo.png";
var srchVal,
    srchValCode,
    srchValExp,
    keyDnWhich;

function getStreamer(userId) {
    $.ajax({
        url: "https://api.twitch.tv/kraken/streams/" + userId + "?client_id=5pkoj4ejkapzxzgq1f3a7dbry59s2r&duration=0&cache=false&noStore=true&callback=?",
        dataType: "jsonp",
        success: function(responseData) {
            $.ajax({
                url: "https://api.twitch.tv/kraken/users/" + userId + "?client_id=5pkoj4ejkapzxzgq1f3a7dbry59s2r&duration=0&cache=false&noStore=true&callback=?",
                dataType: "jsonp",
                success: function(respUser) {
                    /*服务器端成功返回数据后隐藏LOADING动画*/
                    $(".loader").css("display", "none");
                    myStatusMove(); //头部状态栏滚动
                    gameNameMove(); //主播信息栏直播节目名超长处理
                    strLink = "https://www.twitch.tv/" + userId;
                    //离线用户头像只能通过url: "https://api.twitch.tv/kraken/users/" + userId + "?client_id=5pkoj4ejkapzxzgq1f3a7dbry59s2r"
                    //获取, 所以上面另外嵌套了一层$.getJSON()
                    if (respUser.logo === null) {
                        respUser.logo = noLogo;
                    }
                    //判断当前是否正在直播
                    if (responseData.stream !== null) {
                        strGame = responseData.stream.game;
                        strView = responseData.stream.viewers;
                        strInfo = responseData.stream;
                        //注:下方用到了<li onclick="strDescToggle()"></li>, 是因为strDescToggle()在$(document).ready();中调用无效(DOM树加载时, AJAX还未完成数据返回, 但放在AJAX success的回调中会出BUG, 本来只需运行一次的实际运行N次, N等于具有class="userDesc"的元素个数
                        $("#twOnline").append('<li onclick="strDescToggle(this)" class="userDesc"><img class="userImg" src = "' + respUser.logo + '"><div class="userInfo"><span class="userName">' + respUser.display_name.toUpperCase() + '</span><br> 直播中: <span class="gameName">' + strGame + '</span><br>观看人数: ' + strView + '</div></li>');
                        $("#twOnline").append('<li style = "display: none;" class="strDetail"><a target="_blank" href=' + strLink + '>' + '<div class="strDesc"><span class="strStart">本次直播开始于: ' + strInfo.created_at.replace(/T/, " ").replace(/Z/, " ") + '</span><br><span class="strStar">主播粉丝数: ' + strInfo.channel.followers + ';&nbsp;&nbsp;总浏览次数: ' + strInfo.channel.views + '</span><br><span class="strVdo">视频高度: ' + strInfo.video_height + 'PX; 平均帧速: ' + Math.round(strInfo.average_fps) + 'FPS; </span><span class="strLang">语言: ' + strInfo.channel.broadcaster_language.toUpperCase() + '</span></div> <img src = ' + strInfo.preview.medium + ' alt = "strGame" class = "strImg"></a></li>');
                    } else {
                        $("#twOffline").append('<li class="userDesc"><a target="_blank" href=' + strLink + '>' + '<img class="userImg gray" src = "' + respUser.logo + '"><div class="userInfo"><span class="userName">' + respUser.display_name.toUpperCase() + '</span><br> 离线</div></a></li>');
                    }
                },
                error: function(error) {
                    console.log("已获取到stream信息但未获取到user信息, 返回的错误为: " + JSON.stringify(error));
                }
            });
        },
        error: function(error) {
            console.log("未获取到stream信息, 返回的错误为: " + JSON.stringify(error));
        }
    });
}

function twListHeight() {
    //console.log($(window).height() - $("#twList").offset().top - 10);
    $("#twList").css("height", $(window).height() - $("#twList").offset().top - 10);
}

/*状态栏超长字符滚动效果*/
function myStatusMove() {
    //console.log($("#myStatus").width());
    var overWidth = 3140 - $(".myStatus").width();
    //$("#myStatus").css("transform", "translateX(" + (0 - overWidth) + "px)");
    //$("#myStatus").css("transform", "translateX(0)");
    document.styleSheets[2].deleteRule(1);
    //document.styleSheets[2].insertRule("@keyframes myStatusMove { 0% { transform: translateX(0); color: #fff;} 50% {transform: translateX(-240px); color: #E64C65;} 100% { transform: translateX(0); color: #fff; }}", 1);
    document.styleSheets[2].insertRule("@keyframes myStatusMove { 0% { transform: translateX(0); color: #00FFFF;} 100% {transform: translateX(" + (0 - overWidth) / 2 + "px); color: #FFFF00;}}", 1);
}

function gameNameMove() {
    var maxWidth = $("#container").width() - 190;
    $(".gameName").css("max-width", maxWidth);
}

//点击主播信息栏可展开/收起其下方的视频信息
function strDescToggle(ele) {
    var eleStyle = $(ele).next()[0].style;
    //console.log(eleStyle);
    if (eleStyle.display === "none") {
        eleStyle.display = "block";
    } else {
        eleStyle.display = "none";
    }
}

/*CSS中media query只能适配屏幕大小的变化, 本例比较特殊, 因为通过jQuery UI可以在屏幕大小固定的情况下拖动边框改变container的大小, 故需js中在定义监听*/
function respCont() {
    $("#container").resize(function() {
        //console.log($(this).width());
        var contWidth = $(this).width();
        if (contWidth <= 340) {
            $(".myTitle").css("font-size", "1.1em");
            $(".myStatus").css("font-size", "0.9em");
        } else if (contWidth >= 341 && contWidth <= 400) {
            $(".myTitle").css("font-size", "1.2em");
            $(".myStatus").css("font-size", "1em");
        }
        if (contWidth <= 412) {
            $(".strDesc").css({
                "text-align": "center",
                "width": "100%",
                "padding": "4px 0"
            });
            $(".strDesc span").css("font-size", "14px");
            $(".strImg").css({
                "height": "74px",
                "padding": "13px 2px",
                "display": "none"
            });
        } else if (contWidth >= 413 && contWidth <= 455) {
            $(".strDesc").css({
                "float": "left",
                "text-align": "left",
                "width": "calc(100% - 140px)",
                "padding": "4px 0 4px 4px"
            });
            $(".strDesc span").css("font-size", "12px");
            $(".strImg").css({
                "height": "74px",
                "padding": "13px 2px",
                "display": "inline-block"
            });
        } else if (contWidth >= 456 && contWidth <= 535) {
            $(".strDesc").css({
                "float": "left",
                "text-align": "left",
                "width": "calc(100% - 158px)",
                "padding": "4px 0 4px 4px"
            });
            $(".strDesc span").css("font-size", "13px");
            $(".strImg").css({
                "height": "80px",
                "padding": "10px 4px",
                "display": "inline-block"
            });
        }
    });
}

$(document).ready(function() {
    //借助jQuery UI方法使得整个消息框可以在一定范围内随意拖动和改变大小,
    //参考http: //www.runoob.com/jqueryui/example-draggable.html
    $("#container").draggable();
    $("#container").resizable({
        handles: 'n, e, w, ne, nw'
    });

    twListHeight();
    myStatusMove();
    gameNameMove();
    respCont();
    $(window).resize(function() {
        twListHeight();
        myStatusMove();
        gameNameMove();
    });

    for (var i in userIdArr) {
        getStreamer(userIdArr[i]);
    }

    $("#navAll").click(function() {
        showAll();
    });

    $("#navOnline").click(function() {
        showOnline();
    });

    $("#navOffline").click(function() {
        showOffline();
    });

    function showAll() {
        $("#navAll").addClass("active");
        $("#navOnline").removeClass("active");
        $("#navOffline").removeClass("active");
        $("#twOnline").css("display", "block");
        $("#twOffline").css("display", "block");
    }

    function showOnline() {
        $("#navOnline").addClass("active");
        $("#navAll").removeClass("active");
        $("#navOffline").removeClass("active");
        $("#twOnline").css("display", "block");
        $("#twOffline").css("display", "none");
    }

    function showOffline() {
        $("#navOffline").addClass("active");
        $("#navAll").removeClass("active");
        $("#navOnline").removeClass("active");
        $("#twOnline").css("display", "none");
        $("#twOffline").css("display", "block");
    }

    $("#srchIpt").on("input", function() {
        keydnwhich();
        srchVal = $(this).val();
        srchValCode = srchVal.charCodeAt(srchVal.length - 1);
        // srchValCode !== 32 屏蔽中文拼音输入(候选词状态)时srchVal变化的BUG
        if (srchValCode !== 32) {
            //console.log(srchValCode);
            //如果按下了退格键, 则将之前隐藏的结果都显示出来再重新匹配
            if (keyDnWhich === "Backspace") {
                //console.log("按下了退格键");
                $(".userDesc").css("display", "block");
            }
            $(".strDetail").css("display", "none");
            hideUnMatch();
        }

        /*通过keydown()事件监听, 并通过window.event.key得到按下的键值,
        从而判断是否按下了退格键, 供上面函数调用作进一步处理*/
        function keydnwhich() {
            $("#srchIpt").keydown(function() {
                var keyDnEvt = window.event;
                keyDnWhich = keyDnEvt.key;
            });
        }

        //搜索时隐藏不匹配的结果
        function hideUnMatch() {
            srchValExp = new RegExp(srchVal.toUpperCase());

            var onlineList = $("#twOnline").children();
            var offlineList = $("#twOffline").children();
            for (var j = 0; j < onlineList.length; j++) {
                if (!srchValExp.test($($("#twOnline .userName")[j]).html())) {
                    $("#twOnline li:nth-Child(" + (j + 1) + ")").css("display", "none");
                }
            }

            for (var k = 0; k < offlineList.length; k++) {
                if (!srchValExp.test($($("#twOffline .userName")[k]).html())) {
                    $("#twOffline li:nth-Child(" + (k + 1) + ")").css("display", "none");
                }
            }
        }
    });

    //手机端触摸事件监听及左右滑动切换菜单
    function touchMove() {
        var currentX = 0;
        var lastX = 0;
        var moveTo = null;
        $(document).on('touchmove', function(e) {
            // clearTimeout(lastT);
            currentX = e.originalEvent.touches[0].clientX;
            if (lastX === 0) {
                lastX = currentX;
            }
        });

        $(document).on("touchend", function(e) {
            if (currentX) {
                if (currentX - lastX > 0) {
                    moveTo = "right";
                } else if (currentX - lastX < 0) {
                    moveTo = "left";
                }
            }
            //console.log(moveTo);
            if (moveTo === "left") {
                if ($("#navAll").hasClass("active")) {
                    showOnline();
                } else if ($("#navOnline").hasClass("active")) {
                    showOffline();
                } else if ($("#navOffline").hasClass("active")) {
                    showAll();
                }
            } else if (moveTo === "right") {
                if ($("#navAll").hasClass("active")) {
                    showOffline();
                } else if ($("#navOnline").hasClass("active")) {
                    showAll();
                } else if ($("#navOffline").hasClass("active")) {
                    showOnline();
                }
            }
            //每次运行后重置
            currentX = 0;
            lastX = 0;
            moveTo = null;
        });
    }
    touchMove();
});
<div id="container" class="container-fluid">
        <div id="headArea" class="headArea">
            <img src="https://www.mike652638.com/demo/twitch/img/myLogo.png">
            <div class="titleArea">
                <h1 class="myTitle">
                    <a target="_blank" href="https://www.mike652638.com/twitch-code.html">TWITCH-推奇直播</a>
                </h1>
                <h2 class="myStatus">这个小页面主要是利用jQuery的$.getJSON()方法从api.twitch.tv获取关注主播的在线状态及直播信息&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这个小页面主要是利用jQuery的$.getJSON()方法从api.twitch.tv获取关注主播的在线状态及直播信息</h2>
                <div class="clearfix"></div>
            </div>
            <div class="srcCode">
                <a class="srcLink" href="https://github.com/mike652638/twitch-broadcasters" target="_blank">源码
                </a>
            </div>
        </div>
        <div class="search">
            <input type="button" name="srchBtn" class="srchBtn" value="搜索">
            <input type="text" name="srchIpt" class="srchIpt" id="srchIpt">
        </div>
        <ul id="navBar">
            <li id="navAll" class="active">全部主播</li>
            <li id="navOnline">正在直播</li>
            <li id="navOffline">当前离线</li>
        </ul>
        <!-- AJAX成功从服务器返回数据前显示"正在加载"的动画, 更好的用户体验
        LOADING动画节选自http://www.raphaelfabeni.com.br/css-loader/, 致敬原作者raphaelfabeni -->
        <div class="loader loader-bar is-active">
            <span class="loader-text">加载中, 请稍候 ...</span>
        </div>
        <div id="twList" class="twList">
            <ul id="twOnline" class="twOnline">
                <!-- AJAX中加入 -->
                <!-- <li class="strDetail">
                    <div class="strDesc">
                        <span class="strStart">本次直播开始于: 2017-06-02 03:03:39</span>
                        <br><span class="strVdo">视频高度: 720PX; 平均帧速: 62FPS; 语言: PT</span>
                        <br> <span class="strStar">主播粉丝数: 187092;&nbsp;&nbsp;总浏览次数: 6597525</span>
                    </div>
                    <img src="https://static-cdn.jtvnw.net/previews-ttv/live_user_rakin-320x180.jpg" alt="" class="strImg">
                </li> -->
            </ul>
            <ul id="twOffline" class="twOffline"></ul>
        </div>
    </div>
body {
    color: #fff;
    background-color: #1f253d;
    font-family: "Microsoft Yahei", "Sans-Serif";
}

.container-fluid {
    position: relative;
    /**width: 540px;**/
    min-width: 300px;
    max-width: 600px;
    margin: 0 auto;
    overflow: hidden;
}

.headArea {
    height: 80px;
    padding: 10px 10px 14px 10px;
    cursor: move;
    text-align: center;
    border-radius: 0 !important;
    background-color: #3468af;
}

.headArea img {
    float: left;
    width: 80px;
    -webkit-transition: all .5s ease-in;
    transition: all .5s ease-in;
    -webkit-filter: drop-shadow(2px 4px 10px #80ffff);
    filter: drop-shadow(2px 4px 10px #80ffff);
}

.headArea img:hover {
    -webkit-transform: rotate(720deg);
    transform: rotate(720deg);
}

.titleArea {
    overflow: hidden;
    width: calc(100% - 120px);
    margin-left: 100px;
}

.myTitle {
    font-size: 1.6em;
    font-weight: bold;
    margin: 8px 8px 8px 0;
    text-align: left;
    white-space: nowrap;
}

.myTitle a:link,
.myTitle a:visited {
    text-decoration: none;
    color: #fff;
}

.myTitle a:hover,
.myTitle a:active {
    text-decoration: none;
    color: #ff0;
}

.myStatus {
    font-size: 1.2em;
    margin: 6px;
    text-align: left;
    white-space: nowrap;
    /* animation: mymove 10s infinite; */
}

.srcCode {
    position: absolute;
    top: 2px;
    right: -26px;
    transform: rotate(45deg);
    overflow: hidden;
    z-index: 100;
}

.srcLink {
    display: inline-block;
    padding: 0 6px 2px 6px;
    vertical-align: middle;
    text-decoration: none;
    color: #fff;
    background-color: #0080FF;
    text-align: center;
    width: 70px;
    margin-top: 4px;
    border: 1px dashed #fff;
    font-size: 1em;
}

.srcLink:hover {
    text-decoration: none;
    color: #fff;
    background-color: #0080ff;
    -webkit-box-shadow: 2px 2px 20px #000;
    box-shadow: 2px 2px 20px #000;
}


/* 注: 这部分放到了html head标签内,
是因为在js中要用document.styleSheets[2].deleteRule(1)
和document.styleSheets[2].insertRule("", 1)
来动态控制keyframes的transform: translateX()
实现响应式滚动字幕, 放在css是无法实现的

@keyframes mymove {
    0% {
        transform: translateX(0);
        color: #fff;
    }
    50% {
        transform: translateX(-240px);
        color: #E64C65;
    }
    100% {
        transform: translateX(0);
        color: #fff;
    }
} */

.search {
    overflow-x: hidden;
    width: 100%;
    white-space: nowrap;
    background-color: #3468af;
}

.srchBtn,
.srchIpt {
    font-size: 16px;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    vertical-align: middle;
    color: #fff;
    border: 1px solid #fff;
    background-color: #11a8ab;
}

.srchBtn {
    width: 40px;
    height: 28px;
    padding: 2px 3px;
}

.srchIpt {
    width: calc(100% - 39px);
    height: 28px;
    margin-left: -6px;
    padding: 4px;
    text-transform: uppercase;
}

ul#navBar {
    font-size: 1.1em;
    margin: auto;
    padding: 0;
    text-align: center;
    background-color: #e64c65;
}

#navBar li {
    display: inline-block;
    width: 25%;
    padding: 10px;
    cursor: pointer;
    text-align: center;
}

#navBar li:hover {
    background-color: #cc324b;
}

.active {
    background-color: #cc324b;
    /* 底部加描边小技巧 */
    -webkit-box-shadow: inset 0 -5px 0 0 #4fc4f6;
    box-shadow: inset 0 -5px 0 0 #4fc4f6;
}

#twList {
    overflow-y: scroll;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    border: 1px solid #3468af;
    background-color: #3468af;
    overdlow-x: auto;
}

#twList .userImg {
    display: inline-block;
    float: left;
    width: 80px;
    height: 80px;
    margin: 4px 14px;
    -webkit-transition: all .5s ease-in;
    transition: all .5s ease-in;
    border-radius: 50%;
    border: 6px solid #F39A3F;
}

#twList .userImg:hover {
    -webkit-transform: rotate(720deg);
    transform: rotate(720deg);
}

#twList ul {
    margin: 0;
    padding: 0;
    list-style-type: none;
}

.userDesc {
    width: 100%;
    height: 100px;
    margin: 4px 0;
    cursor: pointer;
    background-color: #394264;
}

.userDesc:hover {
    -webkit-box-shadow: 2px 2px 80px 10px #80ffff inset;
    box-shadow: 2px 2px 80px 10px #80ffff inset;
}

.userDesc:first-child {
    margin-top: 10px;
}

.userDesc:last-child {
    margin-bottom: 10px;
}

#twList a:link,
#twList a:visited,
#twList a:hover,
#twList a:active {
    color: #fff;
}

#twList .userInfo {
    display: inline-block;
    float: left;
}

#twList .userName {
    font-size: 1.2em;
    font-weight: bold;
    display: inline-block;
    margin: 10px 0;
    color: #4fc4f6;
}


/* 某些正在直播的游戏名称可能超长,
在iPhone 5等小屏手机上会导致BUG(LOGO及直播信息错位或消失等),
专门针对超长的游戏名称做滚动字幕处理 */

#twOnline .gameName {
    display: inline-block;
    overflow: hidden;
    vertical-align: bottom;
    /* width: calc(100% - 174px); */
    white-space: nowrap;
}

.strDetail {
    margin-top: -4px;
    height: 100px;
    -webkit-transition: all .5s ease-in;
    transition: all .5s ease-in;
    background-color: #8000ff;
}

.strDesc {
    float: left;
    padding: 4px 0 4px 6px;
}

.strDesc span {
    line-height: 30px;
}

.strImg {
    float: right;
    height: 92px;
    padding: 4px;
    -webkit-filter: drop-shadow(4px 4px 20px #80ffff);
    filter: drop-shadow(4px 4px 20px #80ffff);
}


/* 用户离线状态时, 其LOGO加一层黑白滤镜 */

.gray {
    -webkit-filter: grayscale(100%);
    -moz-filter: grayscale(100%);
    -ms-filter: grayscale(100%);
    -o-filter: grayscale(100%);
    filter: grayscale(100%);
    -webkit-filter: gray;
    filter: gray;
}


/* 浏览器默认的滚动条样式与页面不是很搭, 所以下面自定义了一下 */

::-webkit-scrollbar-track {
    border-radius: 0;
    background-color: rgba(0, 255, 255, .2);
    -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
}

::-webkit-scrollbar {
    width: 10px;
    background-color: rgba(0, 255, 255, .2);
}

::-webkit-scrollbar-thumb {
    border-radius: 0;
    background-image: -webkit-gradient(linear, left bottom, left top, color-stop(.44, rgb(28, 58, 148)), color-stop(.86, rgb(122, 153, 217)), color-stop(.72, rgb(73, 125, 189)));
}


/* AJAX成功从服务器返回数据前显示"正在加载"的动画, 更好的用户体验
LOADING动画节选自http://www.raphaelfabeni.com.br/css-loader/, 致敬原作者raphaelfabeni */

.loader {
    overflow: hidden;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    color: #fff;
}

.loader.is-active:after,
.loader.is-active:before {
    display: block;
}

.loader-bar:after {
    position: fixed;
    top: 62%;
    left: 50%;
    width: 200px;
    height: 20px;
    content: '';
    -webkit-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
    -webkit-animation: moveBar 1.5s linear infinite reverse;
    animation: moveBar 1.5s linear infinite reverse;
    background: linear-gradient(-45deg, #4183d7 25%, #52b3d9 25%, #52b3d9 50%, #4183d7 50%, #4183d7 75%, #52b3d9 75%, #52b3d9);
    background-size: 20px 20px;
    -webkit-box-shadow: inset 0 10px 0 rgba(255, 255, 255, .2), 0 0 0 5px rgba(0, 0, 0, .2);
    box-shadow: inset 0 10px 0 rgba(255, 255, 255, .2), 0 0 0 5px rgba(0, 0, 0, .2);
}

.loader-text {
    position: fixed;
    top: 57%;
    left: 50%;
    -webkit-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
}

@-webkit-keyframes moveBar {
    from {
        background-position: 0 0;
    }
    to {
        background-position: 20px 20px;
    }
}

@keyframes moveBar {
    from {
        background-position: 0 0;
    }
    to {
        background-position: 20px 20px;
    }
}

@media screen and (min-width: 456px) and (max-width: 535px) {
    .strDesc span {
        font-size: 13px;
    }
    .strImg {
        height: 80px;
        padding: 10px 4px;
    }
}

@media screen and (min-width: 413px) and (max-width: 455px) {
    .strDesc {
        padding-right: 0;
    }
    .strDesc span {
        font-size: 12px;
    }
    .strImg {
        height: 74px;
        padding: 13px 2px;
    }
    .strLang {
        display: none;
    }
}

@media screen and (max-width: 412px) {
    .strDesc {
        width: 100%;
        padding: 4px 0;
        text-align: center;
    }
    .strDesc span {
        font-size: 14px;
    }
    .strImg {
        display: none;
    }
}

@media screen and (min-width: 341px) and (max-width: 400px) {
    .myTitle {
        font-size: 1.2em;
    }
    .myStatus {
        font-size: 1em;
    }
}

@media screen and (max-width: 340px) {
    .myTitle {
        font-size: 1.1em;
    }
    .myStatus {
        font-size: .9em;
    }
}

本项目引用的自定义外部资源