Форум Pawn.Wiki - Воплоти мечту в реальность!: Виджеты - Форум Pawn.Wiki - Воплоти мечту в реальность!

Перейти к содержимому

  • (2 Страниц) +
  • 1
  • 2
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

Виджеты Оценка: -----

#1
Пользователь офлайн   NiceXPlayer 

  • Пользователь
  • Вставить ник
  • Раскрыть информацию
Всем привет. С этого дня я начинаю делать виджеты. Многие работы являются лишь доработкой и не более. Там где мои - я так и напишу. Моё.

Виджет Плейлиста
Автор данной системы: CodingNepal. Доработал и перевел под реалии SA-MP Я, помогал Кирилл.

Для начала начнем с описание что это вообще такое. Многие знают что такое виджеты? Вывод на экран прочей информации. На данный момент готов плеер. В будущем попробуем соединить все в одно меню.

Вышла версия 0.2.1 FIX https://disk.yandex..../l7QtWpr-TdfgZQ


Обзор первого виджета


1. Давайте создадим папку и назовем ее например musicserver. Внутри папки создадим данные файлы:
-Папку images
-Папку songs
- index.html
- style.css
- move.js
- Папку js. Внутри папки js создадим файлы music-list.js и script.js .

Чтобы добавлять свои картинки и аудио, для этого вам нужно сказать музыку и изображение. Обязательно mp3 и jpg.
- mp3 файл закинуть в songs и переименовать в music-?
- img файл закинуть в images и переименовать в music-?
Добавлять плейлисты в music-list.js там и указывать свои названия.


Готовый и рабочий вариант: https://disk.yandex..../ScG5haR4O-BOMw
Ссылка на CEF: https://disk.yandex..../2PEaVmWpsNqrOA


2. В Index.html добавим


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Music Player</title>
  <link rel="stylesheet" href="style.css">
  <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
</head>
<body>
<div id="draggable">
  <div class="wrapper">
    <div class="top-bar">
      <span>Сейчас играет</span>
    </div>
    <div class="img-area">
      <img src="" alt="">
    </div>
    <div class="song-details">
      <p class="name"></p>
      <p class="artist"></p>
    </div>
    <div class="progress-area">
      <div class="progress-bar">
        <audio id="main-audio" src=""></audio>
      </div>
      <div class="song-timer">
        <span class="current-time">0:00</span>
        <span class="max-duration">0:00</span>
      </div>
    </div>
    <div class="controls">
      <i id="repeat-plist" class="material-icons" title="Playlist looped">repeat</i>
      <i id="prev" class="material-icons">skip_previous</i>
      <div class="play-pause">
        <i class="material-icons play">play_arrow</i>
      </div>
      <i id="next" class="material-icons">skip_next</i>
      <i id="more-music" class="material-icons">queue_music</i>
    </div>
    <div class="music-list">
      <div class="header">
        <div class="row">
          <i class= "list material-icons">queue_music</i>
          <span>Плейлист</span>
        </div>
        <i id="close" class="material-icons">close</i>
      </div>
      <ul>
        <!-- here li list are coming from js -->
      </ul>
    </div>
  </div>
  </div>
  <script src="js/music-list.js"></script>
  <script src="js/script.js"></script>
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  <script>

    $( "#draggable" ).draggable();

  </script>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <script>
            $(this).keydown(function(eventObject){
                if (eventObject.which == 27) //буква ESC
                {
                        cef.hide(false); 
                        cef.set_focus(false); 
                }
                    
            });
</script>

</body>
</html>



3. В style.css добавим

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Poppins", sans-serif;
}
*::before, *::after{
  padding: 0;
  margin: 0;
}
:root{
  --pink: #ff74a4;
  --violet: #9f6ea3;
  --lightblack: #515C6F;
  --white: #ffffff;
  --darkwhite: #cecaca;
  --pinkshadow: #ffcbdd;
  --lightbshadow: rgba(0,0,0,0.15);
}
body{
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  overflow:hidden;
  background:transparent;
}
.wrapper{
  width: 380px;
  padding: 25px 30px;
  overflow: hidden;
  position: relative;
  border-radius: 15px;
  background: var(--white);
  box-shadow: 0px 6px 15px var(--lightbshadow);
}
.wrapper i{
  cursor: pointer;
}
.top-bar, .progress-area .song-timer, 
.controls, .music-list .header, .music-list ul li{
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.top-bar i{
  font-size: 30px;
  color: var(--lightblack);
}
.top-bar i:first-child{
  margin-left: -7px;
}
.top-bar span{
  font-size: 18px;
  margin-left: -3px;
  color: var(--lightblack);
}
.img-area{
  width: 100%;
  height: 176px;
  overflow: hidden;
  margin-top: 25px;
  border-radius: 15px;
  box-shadow: 0px 6px 12px var(--lightbshadow);
}
.img-area img{
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.song-details{
  text-align: center;
  margin: 30px 0;
}
.song-details p{
  color: var(--lightblack);
}
.song-details .name{
  font-size: 21px;
}
.song-details .artist{
  font-size: 18px;
  opacity: 0.9;
  line-height: 35px;
}
.progress-area{
  height: 6px;
  width: 100%;
  border-radius: 50px;
  background: #f0f0f0;
  cursor: pointer;
}
.progress-area .progress-bar{
  height: inherit;
  width: 0%;
  position: relative;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--pink) 0%, var(--violet) 100%);
}
.progress-bar::before{
  content: "";
  position: absolute;
  height: 12px;
  width: 12px;
  border-radius: 50%;
  top: 50%;
  right: -5px;
  z-index: 2;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-50%);
  background: inherit;
  transition: opacity 0.2s ease;
}
.progress-area:hover .progress-bar::before{
  opacity: 1;
  pointer-events: auto;
}
.progress-area .song-timer{
  margin-top: 2px;
}
.song-timer span{
  font-size: 13px;
  color: var(--lightblack);
}
.controls{
  margin: 40px 0 5px 0;
}
.controls i{
  font-size: 28px;
  user-select: none;
  background: linear-gradient(var(--pink) 0%, var(--violet) 100%);
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}
.controls i:nth-child(2),
.controls i:nth-child(4){
  font-size: 43px;
}
.controls #prev{
  margin-right: -13px;
}
.controls #next{
  margin-left: -13px;
}
.controls .play-pause{
  height: 54px;
  width: 54px;
  display: flex;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: linear-gradient(var(--white) 0%, var(--darkwhite) 100%);
  box-shadow: 0px 0px 5px var(--pink);
}
.play-pause::before{
  position: absolute;
  content: "";
  height: 43px;
  width: 43px;
  border-radius: inherit;
  background: linear-gradient(var(--pink) 0%, var(--violet) 100%);
}
.play-pause i{
  height: 43px;
  width: 43px;
  line-height: 43px;
  text-align: center;
  background: inherit;
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  position: absolute;
}
.music-list{
  position: absolute;
  background: var(--white);
  width: 100%;
  left: 0;
  bottom: -55%;
  opacity: 0;
  pointer-events: none;
  z-index: 5;
  padding: 15px 30px;
  border-radius: 15px;
  box-shadow: 0px -5px 10px rgba(0,0,0,0.1);
  transition: all 0.15s ease-out;
}
.music-list.show{
  bottom: 0;
  opacity: 1;
  pointer-events: auto;
}
.header .row{
  display: flex;
  align-items: center;
  font-size: 19px;
  color: var(--lightblack);
}
.header .row i{
  cursor: default;
}
.header .row span{
  margin-left: 5px;
}
.header #close{
  font-size: 22px;
  color: var(--lightblack);
}
.music-list ul{
  margin: 10px 0;
  max-height: 260px;
  overflow: auto;
}
.music-list ul::-webkit-scrollbar{
  width: 0px;
}
.music-list ul li{
  list-style: none;
  display: flex;
  cursor: pointer;
  padding-bottom: 10px;
  margin-bottom: 5px;
  color: var(--lightblack);
  border-bottom: 1px solid #E5E5E5;
}
.music-list ul li:last-child{
  border-bottom: 0px;
}
.music-list ul li .row span{
  font-size: 17px;
}
.music-list ul li .row p{
  opacity: 0.9;
}
ul li .audio-duration{
  font-size: 16px;
}
ul li.playing{
  pointer-events: none;
  color: var(--violet);
}


4. В music-list.js добавим

let allMusic = [
  {
    name: "Gta San Andreas",
    artist: "Game",
    img: "music-1",
    src: "music-1"
  },
  {
    name: "Смешарики",
    artist: "Songs",
    img: "music-2",
    src: "music-2"
  },

];


5. В script.js добавим

const wrapper = document.querySelector(".wrapper"),
musicImg = wrapper.querySelector(".img-area img"),
musicName = wrapper.querySelector(".song-details .name"),
musicArtist = wrapper.querySelector(".song-details .artist"),
playPauseBtn = wrapper.querySelector(".play-pause"),
prevBtn = wrapper.querySelector("#prev"),
nextBtn = wrapper.querySelector("#next"),
mainAudio = wrapper.querySelector("#main-audio"),
progressArea = wrapper.querySelector(".progress-area"),
progressBar = progressArea.querySelector(".progress-bar"),
musicList = wrapper.querySelector(".music-list"),
moreMusicBtn = wrapper.querySelector("#more-music"),
closemoreMusic = musicList.querySelector("#close");
let musicIndex = Math.floor((Math.random() * allMusic.length) + 1);
isMusicPaused = true;
window.addEventListener("load", ()=>{
  loadMusic(musicIndex);
  playingSong(); 
});
function loadMusic(indexNumb){
  musicName.innerText = allMusic[indexNumb - 1].name;
  musicArtist.innerText = allMusic[indexNumb - 1].artist;
  musicImg.src = `images/${allMusic[indexNumb - 1].src}.jpg`;
  mainAudio.src = `songs/${allMusic[indexNumb - 1].src}.mp3`;
}
//play music function
function playMusic(){
  wrapper.classList.add("paused");
  playPauseBtn.querySelector("i").innerText = "pause";
  mainAudio.play();
}
//pause music function
function pauseMusic(){
  wrapper.classList.remove("paused");
  playPauseBtn.querySelector("i").innerText = "play_arrow";
  mainAudio.pause();
}
//prev music function
function prevMusic(){
  musicIndex--; //decrement of musicIndex by 1
  //if musicIndex is less than 1 then musicIndex will be the array length so the last music play
  musicIndex < 1 ? musicIndex = allMusic.length : musicIndex = musicIndex;
  loadMusic(musicIndex);
  playMusic();
  playingSong(); 
}
//next music function
function nextMusic(){
  musicIndex++; //increment of musicIndex by 1
  //if musicIndex is greater than array length then musicIndex will be 1 so the first music play
  musicIndex > allMusic.length ? musicIndex = 1 : musicIndex = musicIndex;
  loadMusic(musicIndex);
  playMusic();
  playingSong(); 
}
// play or pause button event
playPauseBtn.addEventListener("click", ()=>{
  const isMusicPlay = wrapper.classList.contains("paused");
  //if isPlayMusic is true then call pauseMusic else call playMusic
  isMusicPlay ? pauseMusic() : playMusic();
  playingSong();
});
//prev music button event
prevBtn.addEventListener("click", ()=>{
  prevMusic();
});
//next music button event
nextBtn.addEventListener("click", ()=>{
  nextMusic();
});
// update progress bar width according to music current time
mainAudio.addEventListener("timeupdate", (e)=>{
  const currentTime = e.target.currentTime; //getting playing song currentTime
  const duration = e.target.duration; //getting playing song total duration
  let progressWidth = (currentTime / duration) * 100;
  progressBar.style.width = `${progressWidth}%`;
  let musicCurrentTime = wrapper.querySelector(".current-time"),
  musicDuartion = wrapper.querySelector(".max-duration");
  mainAudio.addEventListener("loadeddata", ()=>{
    // update song total duration
    let mainAdDuration = mainAudio.duration;
    let totalMin = Math.floor(mainAdDuration / 60);
    let totalSec = Math.floor(mainAdDuration % 60);
    if(totalSec < 10){ //if sec is less than 10 then add 0 before it
      totalSec = `0${totalSec}`;
    }
    musicDuartion.innerText = `${totalMin}:${totalSec}`;
  });
  // update playing song current time
  let currentMin = Math.floor(currentTime / 60);
  let currentSec = Math.floor(currentTime % 60);
  if(currentSec < 10){ //if sec is less than 10 then add 0 before it
    currentSec = `0${currentSec}`;
  }
  musicCurrentTime.innerText = `${currentMin}:${currentSec}`;
});
// update playing song currentTime on according to the progress bar width
progressArea.addEventListener("click", (e)=>{
  let progressWidth = progressArea.clientWidth; //getting width of progress bar
  let clickedOffsetX = e.offsetX; //getting offset x value
  let songDuration = mainAudio.duration; //getting song total duration
  
  mainAudio.currentTime = (clickedOffsetX / progressWidth) * songDuration;
  playMusic(); //calling playMusic function
  playingSong();
});
//change loop, shuffle, repeat icon onclick
const repeatBtn = wrapper.querySelector("#repeat-plist");
repeatBtn.addEventListener("click", ()=>{
  let getText = repeatBtn.innerText; //getting this tag innerText
  switch(getText){
    case "repeat":
      repeatBtn.innerText = "repeat_one";
      repeatBtn.setAttribute("title", "Song looped");
      break;
    case "repeat_one":
      repeatBtn.innerText = "shuffle";
      repeatBtn.setAttribute("title", "Playback shuffled");
      break;
    case "shuffle":
      repeatBtn.innerText = "repeat";
      repeatBtn.setAttribute("title", "Playlist looped");
      break;
  }
});
//code for what to do after song ended
mainAudio.addEventListener("ended", ()=>{
  // we'll do according to the icon means if user has set icon to
  // loop song then we'll repeat the current song and will do accordingly
  let getText = repeatBtn.innerText; //getting this tag innerText
  switch(getText){
    case "repeat":
      nextMusic(); //calling nextMusic function
      break;
    case "repeat_one":
      mainAudio.currentTime = 0; //setting audio current time to 0
      loadMusic(musicIndex); //calling loadMusic function with argument, in the argument there is a index of current song
      playMusic(); //calling playMusic function
      break;
    case "shuffle":
      let randIndex = Math.floor((Math.random() * allMusic.length) + 1); //genereting random index/numb with max range of array length
      do{
        randIndex = Math.floor((Math.random() * allMusic.length) + 1);
      }while(musicIndex == randIndex); //this loop run until the next random number won't be the same of current musicIndex
      musicIndex = randIndex; //passing randomIndex to musicIndex
      loadMusic(musicIndex);
      playMusic();
      playingSong();
      break;
  }
});
//show music list onclick of music icon
moreMusicBtn.addEventListener("click", ()=>{
  musicList.classList.toggle("show");
});
closemoreMusic.addEventListener("click", ()=>{
  moreMusicBtn.click();
});
const ulTag = wrapper.querySelector("ul");
// let create li tags according to array length for list
for (let i = 0; i < allMusic.length; i++) {
  //let's pass the song name, artist from the array
  let liTag = `<li li-index="${i + 1}">
                <div class="row">
                  <span>${allMusic[i].name}</span>
                  <p>${allMusic[i].artist}</p>
                </div>
                <span id="${allMusic[i].src}" class="audio-duration">3:40</span>
                <audio class="${allMusic[i].src}" src="songs/${allMusic[i].src}.mp3"></audio>
              </li>`;
  ulTag.insertAdjacentHTML("beforeend", liTag); //inserting the li inside ul tag
  let liAudioDuartionTag = ulTag.querySelector(`#${allMusic[i].src}`);
  let liAudioTag = ulTag.querySelector(`.${allMusic[i].src}`);
  liAudioTag.addEventListener("loadeddata", ()=>{
    let duration = liAudioTag.duration;
    let totalMin = Math.floor(duration / 60);
    let totalSec = Math.floor(duration % 60);
    if(totalSec < 10){ //if sec is less than 10 then add 0 before it
      totalSec = `0${totalSec}`;
    };
    liAudioDuartionTag.innerText = `${totalMin}:${totalSec}`; //passing total duation of song
    liAudioDuartionTag.setAttribute("t-duration", `${totalMin}:${totalSec}`); //adding t-duration attribute with total duration value
  });
}
//play particular song from the list onclick of li tag
function playingSong(){
  const allLiTag = ulTag.querySelectorAll("li");
  
  for (let j = 0; j < allLiTag.length; j++) {
    let audioTag = allLiTag[j].querySelector(".audio-duration");
    
    if(allLiTag[j].classList.contains("playing")){
      allLiTag[j].classList.remove("playing");
      let adDuration = audioTag.getAttribute("t-duration");
      audioTag.innerText = adDuration;
    }
    //if the li tag index is equal to the musicIndex then add playing class in it
    if(allLiTag[j].getAttribute("li-index") == musicIndex){
      allLiTag[j].classList.add("playing");
      audioTag.innerText = "Сейчас играет";
    }
    allLiTag[j].setAttribute("onclick", "clicked(this)");
  }
}
//particular li clicked function
function clicked(element){
  let getLiIndex = element.getAttribute("li-index");
  musicIndex = getLiIndex; //updating current song index with clicked li index
  loadMusic(musicIndex);
  playMusic();
  playingSong();
}


6. В move.js добавим

//Make the DIV element draggagle:
dragElement(document.getElementById(("dialogdrag")));

function dragElement(elmnt) {
  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  if (document.getElementById(elmnt.id + "header")) {
    /* if present, the header is where you move the DIV from:*/
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
  } else {
    /* otherwise, move the DIV from anywhere inside the DIV:*/
    elmnt.onmousedown = dragMouseDown;
  }

  function dragMouseDown(e) {
    e = e || window.event;
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    e = e || window.event;
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  }

  function closeDragElement() {
    /* stop moving when mouse button is released:*/
    document.onmouseup = null;
    document.onmousemove = null;
  }
}




Осталось это все прописать в pawn. (Укажу старую инструкцию, позже переделаю)

1. Добавим в начало мода

#include <cef>
#include <fmt>
#include <Pawn.CMD>


2. Ко всем #define

#define CEF_INTERFACE_BROWSER_ID 2


3. Ко всем командам

CMD:cef(playerid) return initialize_interface(playerid);


4. В конец мода

stock initialize_interface(playerid)
{
        cef_create_browser(playerid, CEF_INTERFACE_BROWSER_ID, "Ссылка", false, true);
        return 1;
}



Виджет Онлайна

 NiceXPlayer (07 ноября 2021 - 01:36) писал:

Нажмите сюда, чтобы прочитать мануал по виджету. [Показать]




Виджет озвучки текста

 NiceXPlayer (16 ноября 2021 - 02:43) писал:

Нажмите сюда, чтобы прочитать мануал по виджету [Показать]

Сообщение отредактировал NiceXPlayer: 17 ноября 2021 - 20:22

3

#2
Пользователь офлайн   NiceXPlayer 

  • Пользователь
  • Вставить ник
  • Раскрыть информацию
Вышло обновление виджета плейлиста - теперь полосы перемотки при передвижении не отображаются.
0

#3
Пользователь офлайн   mama123123 

  • Новичок
  • Вставить ник
  • Раскрыть информацию

 NiceXPlayer (02 ноября 2021 - 00:27) писал:

Вышло обновление виджета плейлиста - теперь полосы перемотки при передвижении не отображаются.

Не знаешь когда новая версия cef-a выйдет?
0

#4
Пользователь офлайн   NiceXPlayer 

  • Пользователь
  • Вставить ник
  • Раскрыть информацию

 mama123123 (02 ноября 2021 - 00:58) писал:

Не знаешь когда новая версия cef-a выйдет?


Последнее обновление было 8 дней назад

https://github.com/Z...amp-cef/actions

последнее обновление
0

#5
Пользователь офлайн   SRIPTER MODOV 

  • Пользователь
  • Вставить ник
  • Раскрыть информацию
Вышла вторая версия данного скриптика
Автор доработки: Я ( vk.com/weckek )
Скачать можно: https://github.com/R...eleases/tag/0.2

Виджет также можно и запретить передвигать нажав ESC. Чтобы появился курсор введите /audio , чтобы скрыть нажмите M когда включен курсор.

Коротко и о главном:
-Добавлена смены тема ( по умолчанию черная )
-Добавлена смена громкости
-Добавлена проверка когда игрок в машине , то звук ему ставится ниже, а когда нет , то возвращается до установленной ( внимание проверка машины работает на всех игроках , также как и проверка запущен ли виджет или нет , советую сменить )
-Оптимизирован код JS.

Я это дорабатываю почти каждый день и хочу сделать планшет, а в нем виджет ( как Apple ) и там была музыка .
О всех багах можете писать мне в ЛС : vk.com/weckek

Сообщение отредактировал SRIPTER MODOV: 04 ноября 2021 - 22:26

0

#6
Пользователь офлайн   _54REGION_ 

  • Профессионал
  • Вставить ник
  • Раскрыть информацию
Кнопку свернуть ещё бы добавить а то много места занимает)
0

#7
Пользователь офлайн   NiceXPlayer 

  • Пользователь
  • Вставить ник
  • Раскрыть информацию
Виджет Онлайна

Продолжаем развивать тему с виджетами. На очереди у нас виджет онлайна. Данный виджет будет проверять ваш статус интернета прямо из игры. Система дорабатывалась мной под реалии сампа. Автор не я.




1. Для начала нам нужно создать папку, назвать как хотите и внутри ее создать 3 файла

- index.html
- style.css
- script.js

2. В index.html добавим


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Проверка</title>
  <link rel="stylesheet" href="style.css">
  <link rel="stylesheet" href="https://unicons.iconscout.com/release/v3.0.6/css/line.css">
</head>
<body>
  <div class="wrapper">
      <div class="content">
        <div class="icon"><i class="uil uil-wifi"></i></div>
      </div>
  </div>
  <script src="script.js"></script>
</body>
</html>


3. В style.css добавим

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
body{
  overflow: hidden;
  background: #f2f2f2;
}
.wrapper{
  position: absolute;
  top: 900px;
  left: 15px;
  animation: show_toast 1s ease forwards;
}
@keyframes show_toast {
  0%{
    transform: translateX(-100%);
  }
  40%{
    transform: translateX(10%);
  }
  80%, 100%{
    transform: translateX(20px);
  }
}
.wrapper.hide{
  animation: hide_toast 1s ease forwards;
}
@keyframes hide_toast {
  0%{
    transform: translateX(20px);
  }
  40%{
    transform: translateX(10%);
  }
  80%, 100%{
    opacity: 0;
    pointer-events: none;
    transform: translateX(-100%);
  }
}
.wrapper .toast{
  background: #fff;
  padding: 20px 15px 20px 20px;
  border-radius: 10px;
  border-left: 5px solid #2ecc71;
  box-shadow: 1px 7px 14px -5px rgba(0,0,0,0.15);
  width: 430px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.wrapper .toast.offline{
  border-color: #ccc;
}
.toast .content{
  display: flex;
  align-items: center;
}
.content .icon{
  font-size: 25px;
  color: #fff;
  height: 50px;
  width: 50px;
  text-align: center;
  line-height: 50px;
  border-radius: 50%;
  background: #2ecc71;
}
.toast.offline .content .icon{
  background: #ccc;
}
.content .details{
  margin-left: 15px;
}
.details span{
  font-size: 20px;
  font-weight: 500;
}
.details p{
  color: #878787;
}
.toast .close-icon{
  color: #878787;
  font-size: 23px;
  cursor: pointer;
  height: 40px;
  width: 40px;
  text-align: center;
  line-height: 40px;
  border-radius: 50%;
  background: #f2f2f2;
  transition: all 0.3s ease;
}
.close-icon:hover{
  background: #efefef;
}


4. В script.js добавим

// Выбор всех необходимых элементов
const wrapper = document.querySelector(".wrapper"),
toast = wrapper.querySelector(".toast"),
title = toast.querySelector("span"),
subTitle = toast.querySelector("p"),
wifiIcon = toast.querySelector(".icon"),
closeIcon = toast.querySelector(".close-icon");
window.onload = ()=>{
    function ajax(){
        let xhr = new XMLHttpRequest(); //создание нового объекта XML
        xhr.open("GET", "https://jsonplaceholder.typicode.com/posts", true); //отправка запроса на получение по этому URL
        xhr.onload = ()=>{ //после загрузки ajax
            //если статус ajax равен 200 или меньше 300, это означает, что пользователь получает данные с этого предоставленного URL
            //или его / ее статус ответа - 200, что означает, что он / она в сети
            if(xhr.status == 200 && xhr.status < 300){
                toast.classList.remove("offline");
                title.innerText = "Вы сейчас в сети";
                subTitle.innerText = "Ура! Интернет подключен.";
                wifiIcon.innerHTML = '<i class="uil uil-wifi"></i>';
                closeIcon.onclick = ()=>{ //скрыть всплывающее уведомление при нажатии значка закрытия
                    wrapper.classList.add("hide");
                }
                setTimeout(()=>{ //автоматически скрыть всплывающее уведомление через 5 секунд
                    wrapper.classList.add("hide");
                }, 5000);
            }else{
                offline(); //вызов автономной функции, если статус ajax не равен 200 или не менее 300
            }
        }
        xhr.onerror = ()=>{
            offline(); ////вызов автономной функции, если переданный URL-адрес неверен, или возврат 404 или другой ошибки
        }
        xhr.send(); //отправка запроса на получение на переданный URL
    }
    function offline(){ //функция для офлайн
        wrapper.classList.remove("hide");
        toast.classList.add("offline");
        title.innerText = "Вы сейчас не в сети";
        subTitle.innerText = "Оппс! Интернет отключен.";
        wifiIcon.innerHTML = '<i class="uil uil-wifi-slash"></i>';
    }
    setInterval(()=>{ //эта функция setInterval часто вызывает ajax через 100 мс
        ajax();
    }, 100);
}



Осталось это все интегрировать в саму игру.


1. Заходим в pawno и добавляем в начало мода

#include <cef>
#include <fmt>
#include <Pawn.CMD>


2. Ко всем #define

#define CEF_INTERFACE_BROWSER_ID 2


3. Ко всем командам

CMD:cef(playerid) return initialize_interface(playerid);


4. В конец мода

stock initialize_interface(playerid)
{
        cef_create_browser(playerid, CEF_INTERFACE_BROWSER_ID, "Ссылка", false, true);
        return 1;
}

Сообщение отредактировал NiceXPlayer: 07 ноября 2021 - 01:51

0

#8
Пользователь офлайн   NiceXPlayer 

  • Пользователь
  • Вставить ник
  • Раскрыть информацию
Виджет озвучки текста

Автор CodingNepal. Адаптация под SA:MP - Я


Всем привет, продолжаю развивать идею с виджетами. В этот раз попробуем сделать виджет озвучки текста. Вы спросите, зачем? Ответ прост. Многие записывают видео и не хотят использовать микрофон, и чтобы не качать прочие программы есть простой выход. Использовать виджет. Этот виджет на самом деле можно развить и сделать чтобы окружающие игроки слышали, но это уже потом. Приступим к мануалу.

1. Для начала нам нужно создать папку и внутри ее создать 4 файла. index.html, style.css, script.js и move.js

2. В index.html добавляем следующий код


<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">  
    <link rel="stylesheet" href="style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  </head>
  <body>
  <div id="draggable">
    <div class="wrapper">
      <header>Озвучивание текста</header>
      <form action="#">
        <div class="row">
          <label>Введи текст и выбери русский язык<br>
		  озвучки</label>
          <textarea></textarea>
        </div>
        <div class="row">
          <label>Выбрать голос</label>
          <div class="outer">
            <select></select>
          </div>
        </div>
        <button>Озвучить</button>
      </form>
    </div>
	</div>
    <script src="script.js"></script>
	<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <script>

    $( "#draggable" ).draggable();

  </script>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <script>
            $(this).keydown(function(eventObject){
                if (eventObject.which == 27) //буква ESC
                {
                        cef.hide(false); 
                        cef.set_focus(false); 
                }
                    
});
</script>
  </body>
</html>


3. В style.html добавляем следующий код

/* Import Google Font - Poppins */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
body{
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}
::selection{
  color: #fff;
  background: #5256AD;
}
.wrapper{
  width: 370px;
  padding: 25px 30px;
  border-radius: 7px;
  background: #fff;
  box-shadow: 7px 7px 20px rgba(0,0,0,0.05);
}
.wrapper header{
  font-size: 28px;
  font-weight: 500;
  text-align: center;
}
.wrapper form{
  margin: 35px 0 20px;
}
form .row{
  display: flex;
  margin-bottom: 20px;
  flex-direction: column;
}
form .row label{
  font-size: 18px;
  margin-bottom: 5px;
}
form .row:nth-child(2) label{
  font-size: 17px;
}
form :where(textarea, select, button){
  outline: none;
  width: 100%;
  height: 100%;
  border: none;
  border-radius: 5px;
}
form .row textarea{
  resize: none;
  height: 110px;
  font-size: 15px;
  padding: 8px 10px;
  border: 1px solid #999;
}
form .row textarea::-webkit-scrollbar{
  width: 0px;
}
form .row .outer{
  height: 47px;
  display: flex;
  padding: 0 10px;
  align-items: center;
  border-radius: 5px;
  justify-content: center;
  border: 1px solid #999;
}
form .row select{
  font-size: 14px;
  background: none;
}
form .row select::-webkit-scrollbar{
  width: 8px;
}
form .row select::-webkit-scrollbar-track{
  background: #fff;
}
form .row select::-webkit-scrollbar-thumb{
  background: #888;
  border-radius: 8px;
  border-right: 2px solid #ffffff;
}
form button{
  height: 52px;
  color: #fff;
  font-size: 17px;
  cursor: pointer;
  margin-top: 10px;
  background: #675AFE;
  transition: 0.3s ease;
}
form button:hover{
  background: #4534fe;
}
@media(max-width: 400px){
  .wrapper{
    max-width: 345px;
    width: 100%;
  }
}


4. В script.js добавим следующий код

const textarea = document.querySelector("textarea"),
voiceList = document.querySelector("select"),
speechBtn = document.querySelector("button");
let synth = speechSynthesis,
isSpeaking = true;
voices();
function voices(){
    for(let voice of synth.getVoices()){
        let selected = voice.name === "Google US English" ? "selected" : "";
        let option = `<option value="${voice.name}" ${selected}>${voice.name} (${voice.lang})</option>`;
        voiceList.insertAdjacentHTML("beforeend", option);
    }
}
synth.addEventListener("voiceschanged", voices);
function textToSpeech(text){
    let utterance = new SpeechSynthesisUtterance(text);
    for(let voice of synth.getVoices()){
        if(voice.name === voiceList.value){
            utterance.voice = voice;
        }
    }
    synth.speak(utterance);
}
speechBtn.addEventListener("click", e =>{
    e.preventDefault();
    if(textarea.value !== ""){
        if(!synth.speaking){
            textToSpeech(textarea.value);
        }
        if(textarea.value.length > 80){
            setInterval(()=>{
                if(!synth.speaking && !isSpeaking){
                    isSpeaking = true;
                    speechBtn.innerText = "Convert To Speech";
                }else{
                }
            }, 500);
            if(isSpeaking){
                synth.resume();
                isSpeaking = false;
                speechBtn.innerText = "Pause Speech";
            }else{
                synth.pause();
                isSpeaking = true;
                speechBtn.innerText = "Resume Speech";
            }
        }else{
            speechBtn.innerText = "Повторить";
        }
    }
});


5. В move.js добавим следующий код

dragElement(document.getElementById(("dialogdrag")));

function dragElement(elmnt) {
  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  if (document.getElementById(elmnt.id + "header")) {
    /* if present, the header is where you move the DIV from:*/
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
  } else {
    /* otherwise, move the DIV from anywhere inside the DIV:*/
    elmnt.onmousedown = dragMouseDown;
  }

  function dragMouseDown(e) {
    e = e || window.event;
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    e = e || window.event;
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  }

  function closeDragElement() {
    /* stop moving when mouse button is released:*/
    document.onmouseup = null;
    document.onmousemove = null;
  }
}

0

#9
Пользователь офлайн   Slava23780 

  • Прохожий
  • Вставить ник
  • Раскрыть информацию
как установить плагин? я установил у меня не работает
0

#10
Пользователь офлайн   mama123123 

  • Новичок
  • Вставить ник
  • Раскрыть информацию
А cef перестал работать? Просто у меня сейчас всегда пишет
14:57:14 [TRACE] (6) client::network: [client\src\network.rs:418] CEF Network: CEF didn't connect. Retrying ...
14:57:14 [TRACE] (6) client::network: [client\src\network.rs:332] CEF Network: OpenConnection (127.0.0.1:7779)
Месяц назад еще работал
0

Поделиться темой:


  • (2 Страниц) +
  • 1
  • 2
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

1 человек читают эту тему
0 пользователей, 1 гостей, 0 скрытых пользователей


Яндекс.Метрика