4 changed files with 206 additions and 14 deletions
-
88README.md
-
BINexamples/gophers/demo.gif
-
70examples/gophers/index.html
-
62examples/gophers/main.go
After Width: 1663 | Height: 723 | Size: 596 KiB |
@ -0,0 +1,70 @@ |
|||||
|
<html> |
||||
|
<head> |
||||
|
<meta charset="utf-8"> |
||||
|
<title>goofy gophers</title> |
||||
|
<style> |
||||
|
body { |
||||
|
cursor: none; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
.gopher { |
||||
|
background-image: url('https://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Go_gopher_mascot_bw.png/768px-Go_gopher_mascot_bw.png'); |
||||
|
width: 95px; |
||||
|
height: 95px; |
||||
|
background-size: cover; |
||||
|
position: absolute; |
||||
|
left: 0px; |
||||
|
top: 0px; |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
<body> |
||||
|
<script> |
||||
|
var url = "ws://" + window.location.host + "/ws"; |
||||
|
var ws = new WebSocket(url); |
||||
|
var myid = -1; |
||||
|
|
||||
|
ws.onmessage = function (msg) { |
||||
|
var cmds = {"iam": iam, "set": set, "dis": dis}; |
||||
|
if (msg.data) { |
||||
|
var parts = msg.data.split(" ") |
||||
|
var cmd = cmds[parts[0]]; |
||||
|
if (cmd) { |
||||
|
cmd.apply(null, parts.slice(1)); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
function iam(id) { |
||||
|
myid = id; |
||||
|
} |
||||
|
|
||||
|
function set(id, x, y) { |
||||
|
var node = document.getElementById("gopher-" + id); |
||||
|
if (!node) { |
||||
|
node = document.createElement("div"); |
||||
|
document.body.appendChild(node); |
||||
|
node.className = "gopher"; |
||||
|
node.style.zIndex = id + 1; |
||||
|
node.id = "gopher-" + id; |
||||
|
} |
||||
|
node.style.left = x + "px"; |
||||
|
node.style.top = y + "px"; |
||||
|
} |
||||
|
|
||||
|
function dis(id) { |
||||
|
var node = document.getElementById("gopher-" + id); |
||||
|
if (node) { |
||||
|
document.body.removeChild(node); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
window.onmousemove = function (e) { |
||||
|
if (myid > -1) { |
||||
|
set(myid, e.pageX, e.pageY); |
||||
|
ws.send([e.pageX, e.pageY].join(" ")); |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
</body> |
||||
|
</html> |
@ -0,0 +1,62 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gin-gonic/gin" |
||||
|
"github.com/olahol/melody" |
||||
|
"net/http" |
||||
|
"strconv" |
||||
|
"strings" |
||||
|
"sync" |
||||
|
) |
||||
|
|
||||
|
type GopherInfo struct { |
||||
|
ID, X, Y string |
||||
|
} |
||||
|
|
||||
|
func main() { |
||||
|
router := gin.Default() |
||||
|
mrouter := melody.New() |
||||
|
gophers := make(map[*melody.Session]*GopherInfo) |
||||
|
lock := new(sync.Mutex) |
||||
|
counter := 0 |
||||
|
|
||||
|
router.GET("/", func(c *gin.Context) { |
||||
|
http.ServeFile(c.Writer, c.Request, "index.html") |
||||
|
}) |
||||
|
|
||||
|
router.GET("/ws", func(c *gin.Context) { |
||||
|
mrouter.HandleRequest(c.Writer, c.Request) |
||||
|
}) |
||||
|
|
||||
|
mrouter.HandleConnect(func(s *melody.Session) { |
||||
|
lock.Lock() |
||||
|
for _, info := range gophers { |
||||
|
s.Write([]byte("set " + info.ID + " " + info.X + " " + info.Y)) |
||||
|
} |
||||
|
gophers[s] = &GopherInfo{strconv.Itoa(counter), "0", "0"} |
||||
|
s.Write([]byte("iam " + gophers[s].ID)) |
||||
|
counter += 1 |
||||
|
lock.Unlock() |
||||
|
}) |
||||
|
|
||||
|
mrouter.HandleDisconnect(func(s *melody.Session) { |
||||
|
lock.Lock() |
||||
|
mrouter.BroadcastOthers([]byte("dis "+gophers[s].ID), s) |
||||
|
delete(gophers, s) |
||||
|
lock.Unlock() |
||||
|
}) |
||||
|
|
||||
|
mrouter.HandleMessage(func(s *melody.Session, msg []byte) { |
||||
|
p := strings.Split(string(msg), " ") |
||||
|
lock.Lock() |
||||
|
info := gophers[s] |
||||
|
if len(p) == 2 { |
||||
|
info.X = p[0] |
||||
|
info.Y = p[1] |
||||
|
mrouter.BroadcastOthers([]byte("set "+info.ID+" "+info.X+" "+info.Y), s) |
||||
|
} |
||||
|
lock.Unlock() |
||||
|
}) |
||||
|
|
||||
|
router.Run(":5000") |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue