Unable to Draw a curved polyline using Here Maps JS API.
Trying to add the logic based on my previous findings.
It throws an error "Uncaught TypeError: arc.GreatCircle is not a constructor"
Any Suggestions on how to fix this ?
My Earlier Querstion
Here is my working JSFiddle which is trying to draw a curve to multiple spots.
//Step 1: initialize communication with the platform
// In your own code, replace variable window.apikey with your own apikey
var platform = new H.service.Platform({
apikey: window.apikey
});
var defaultLayers = platform.createDefaultLayers();
//Step 2: initialize a map - this map is centered over Europe
var map = new H.Map(document.getElementById('map'),
defaultLayers.vector.normal.map,{
center: {lat:52, lng:5},
zoom: 5,
pixelRatio: window.devicePixelRatio || 1
});
// add a resize listener to make sure that the map occupies the whole container
window.addEventListener('resize', () => map.getViewPort().resize());
//Step 3: make the map interactive
// MapEvents enables the event system
// Behavior implements default interactions for pan/zoom (also on mobile touch environments)
var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
// Create the default UI components
var ui = H.ui.UI.createDefault(map, defaultLayers);
window.addEventListener('resize', function() { map.getViewPort().resize(); });
var npoints = 100,
offset = 20;
// Now use the map as required...
//addPolylineToMap(map);
// Berlin -> Chicago0
add([52.51607,13.37699],[41.88425,-87.63245], { style: { strokeColor : "#00FF00", lineWidth : 5, lineDash: [3], lineHeadCap: "arrow-head", lineTailCap: "arrow-tail"} });
// Tokyo -> san Francisco
add([35.68019,139.81194],[37.77712,-122.41964], {style: { strokeColor: "rgba(0,0,255,0.7)", lineWidth: 15, lineDash: [1], lineHeadCap: "arrow-head", lineTailCap: "arrow-tail"} });
// Berlin -> Melbourne
add([52.51607,13.37699],[-37.81753,144.96715], { style: { strokeColor : "rgba(255,0,255,0.7)", lineWidth : 5, lineDash: [3], lineHeadCap: "arrow-head", lineTailCap: "arrow-tail"} });
// Berlin -> Paris -> Paris -> London
add([52.51607,13.37699],[48.85721, 2.34144], { style: { strokeColor : "rgba(0,255,0,0.7)", lineWidth : 5, lineDash: [3], lineHeadCap: "arrow-head", lineTailCap: "arrow-tail"} });
add([48.85721, 2.34144],[51.50643,-0.12721], { style: { strokeColor : "rgba(255,255,0,0.7)", lineWidth : 5, lineDash: [3], lineHeadCap: "arrow-head", lineTailCap: "arrow-tail"} });
function add(s,e,options) {
var arc = {};
arc.Coord = Coord;
arc.Arc = Arc;
arc.GreatCircle = GreatCircle;
var start_ll = new H.geo.Point(s[0],s[1]),
end_ll = new H.geo.Point(e[0],e[1]),
start_coord = {x: start_ll.lng, y:start_ll.lat},
end_coord = {x:end_ll.lng, y:end_ll.lat};
description = ''+s[0]+','+s[1]+'=>'+e[0]+','+e[1]+'',
gc0 = new arc.GreatCircle(start_coord,end_coord, {'name': 'line', 'color':'#ff7200','description':description}),
line0 = gc0.Arc(npoints,{offset:offset}),
strip = line0.strip();
map.addObject(new H.map.Polyline(strip, options));
}
var D2R = Math.PI / 180;
var R2D = 180 / Math.PI;
var Coord = function(lon, lat) {
this.lon = lon;
this.lat = lat;
this.x = D2R * lon;
this.y = D2R * lat;
};
Coord.prototype.view = function() {
return String(this.lon).slice(0, 4) + ',' + String(this.lat).slice(0, 4);
};
Coord.prototype.antipode = function() {
var anti_lat = -1 * this.lat;
var anti_lon = (this.lon < 0) ? 180 + this.lon : (180 - this.lon) * -1;
return new Coord(anti_lon, anti_lat);
};
var LineString = function() {
this.coords = [];
this.length = 0;
};
LineString.prototype.move_to = function(coord) {
this.length++;
this.coords.push(coord);
};
var Arc = function(properties) {
this.properties = properties || {};
this.geometries = [];
};
Arc.prototype.json = function() {
if (this.geometries.length <= 0) {
return { 'geometry': { 'type': 'LineString', 'coordinates': null }, 'type': 'Feature', 'properties': this.properties };
} else if (this.geometries.length == 1) {
return { 'geometry': { 'type': 'LineString', 'coordinates': this.geometries[0].coords }, 'type': 'Feature', 'properties': this.properties };
} else {
var multiline = [];
for (var i = 0; i < this.geometries.length; i++) {
multiline.push(this.geometries[i].coords);
}
return { 'geometry': { 'type': 'MultiLineString', 'coordinates': multiline }, 'type': 'Feature', 'properties': this.properties };
}
};
Arc.prototype.strip = function() {
var s = H.geo.Strip ? new H.geo.Strip() : new H.geo.LineString();
for (var i = 0; i < this.geometries.length; i++) {
if (this.geometries[i].coords.lenght !== 0) {
var coords = this.geometries[i].coords;
for (var j = 0; j < coords.length; j++) {
var p = new H.geo.Point(coords[j][1], coords[j][0]);
s.pushPoint(p);
}
}
}
return s;
}
var GreatCircle = function(start, end, properties) {
if (!start || start.x === undefined || start.y === undefined) {
throw new Error("GreatCircle constructor expects two args: start and end objects with x and y properties");
}
if (!end || end.x === undefined || end.y === undefined) {
throw new Error("GreatCircle constructor expects two args: start and end objects with x and y properties");
}
this.start = new Coord(start.x, start.y);
this.end = new Coord(end.x, end.y);
this.properties = properties || {};
var w = this.start.x - this.end.x;
var h = this.start.y - this.end.y;
var z = Math.pow(Math.sin(h / 2.0), 2) + Math.cos(this.start.y) * Math.cos(this.end.y) * Math.pow(Math.sin(w / 2.0), 2);
this.g = 2.0 * Math.asin(Math.sqrt(z));
if (this.g == Math.PI) {
throw new Error('it appears ' + start.view() + ' and ' + end.view() + " are 'antipodal', e.g diametrically opposite, thus there is no single route but rather infinite");
} else if (isNaN(this.g)) {
throw new Error('could not calculate great circle between ' + start + ' and ' + end);
}
};
#map {
width: 95%;
height: 450px;
background: grey;
}
<script src="https://heremaps.github.io/maps-api-for-javascript-examples/test-credentials.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes">
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Polyline on the Map</title>
<link rel="stylesheet" type="text/css" href="https://js.api.here.com/v3/3.1/mapsjs-ui.css" />
<link rel="stylesheet" type="text/css" href="demo.css" />
<link rel="stylesheet" type="text/css" href="styles.css" />
<link rel="stylesheet" type="text/css" href="../template.css" />
<script type="text/javascript" src='../test-credentials.js'></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-core.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-service.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-ui.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js"></script>
</head>
<body id="markers-on-the-map">
<div id="map"></div>
<script type="text/javascript" src='demo.js'></script>
</body>
</html>
this is simple: the var GreatCircle is not defined yet but program code invoke GreatCircle
We moved some parts of code through each together
but any way there is error GreatCircle doesn't have 'arc' property defined.
there is this module https://demo.support.here.com/javascripts/examples/v31/geodesic-polyline.js
but you needs Bézier curve: https://en.wikipedia.org/wiki/B%C3%A9zier_curve
I found some implementation on this https://habr.com/ru/post/163073/ - (but in russian) - there a curve consists from lines based on 100 points (step 0.01)
flow = getBezierCurve(new Array(arr[0], arr[1], arr[2], arr[3]), 0.01);
drawLines(ctx, flow, 10);
In JS API wasn't implemented functionality of like Bézier curve
but search in google on "bezier curve javascript example code" - if you get points of curve you can use in JS API map.screenToGeo every point and plot it on the map
I'm trying to implement a websocket-server with Progress OpenEdge. I still didn't get it working.
I've successfully created a socket-server with the example i-sktsv1.p from here.
When I run my html-page, which looks like:
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8" />
<title>WebSocket Client</title>
<script language="javascript" type="text/javascript">
var wsUri = "ws://localhost:3333/";
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { onOpen(evt) };
// websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
function onOpen(evt) {
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
}
function onClose(evt) {
writeToScreen("DISCONNECTED");
}
function onMessage(evt) {
writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
websocket.close();
}
function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
function doSend(message) {
writeToScreen("SENT: " + message);
websocket.send(message);
}
function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}
window.addEventListener("load", init, false);
</script>
<body>
<h2>WebSocket Test</h2>
<div id="output"></div>
</body>
</html>
I getting a error that the websocket connection could not be established.
The problem is (I think) that Progress offers a socket, not a websocket. Do you know how to get this working?
I have a task that, need to sync my websites's full calendar with google calendar private data. I could able to extract data from google, but while trying to display that to the Jquery full calendar, it shows an error that TypeError: $(...).fullCalendar is not a function, but when page loads full calender is loading properly. I'm getting this error only when refreshing the calendar after fetching data from google.
Here is the code i'm using:
<!DOCTYPE html>
<html>
<head>
<title>Google Calendar API Quickstart</title>
<meta charset='utf-8' />
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.4.0/fullcalendar.css' />
</head>
<body>
<button id="authorize-button" style="display: none;">Authorize</button>
<button id="signout-button" style="display: none;">Sign Out</button>
<pre id="content"></pre>
<div id='calendar'></div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.4.0/fullcalendar.js'></script>
<script type="text/javascript">
var events = [];
$('#calendar').fullCalendar({
eventSources: [
// your event source
{
events: events,
color: 'black', // an option!
textColor: 'yellow' // an option!
}
// any other event sources...
]
});
var CLIENT_ID = 'My Id';
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"];
var SCOPES = "https://www.googleapis.com/auth/calendar.readonly";
var authorizeButton = document.getElementById('authorize-button');
var signoutButton = document.getElementById('signout-button');
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
function initClient() {
gapi.client.init({
discoveryDocs: DISCOVERY_DOCS,
clientId: CLIENT_ID,
scope: SCOPES
}).then(function () {
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
signoutButton.onclick = handleSignoutClick;
});
}
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
authorizeButton.style.display = 'none';
signoutButton.style.display = 'block';
listUpcomingEvents();
} else {
authorizeButton.style.display = 'block';
signoutButton.style.display = 'none';
}
}
function handleAuthClick(event) {
gapi.auth2.getAuthInstance().signIn();
}
function handleSignoutClick(event) {
gapi.auth2.getAuthInstance().signOut();
}
function appendPre(message) {
var pre = document.getElementById('content');
var textContent = document.createTextNode(message + '\n');
pre.appendChild(textContent);
}
function refreshCalander(eventData) {
$('#calendar').fullCalendar({
eventSources: [
// your event source
{
events: eventData,
color: 'black', // an option!
textColor: 'yellow' // an option!
}
// any other event sources..
]
});
}
function listUpcomingEvents() {
gapi.client.calendar.events.list({
'calendarId': 'primary',
'timeMin': (new Date()).toISOString(),
'showDeleted': false,
'singleEvents': true,
'maxResults': 10,
'orderBy': 'startTime'
}).then(function (response) {
var googleEvents = response.result.items;
if (googleEvents.length > 0) {
for (i = 0; i < googleEvents.length; i++) {
var event = googleEvents[i];
var when = event.start.dateTime;
if (!when) {
when = event.start.date;
}
events.push({ "title": event.summary, "start": when });
}
refreshCalander(events);
}
});
}
</script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body>
</html>
I have a requirement of capturing video with audio from users and upload it to the server. I have worked around with Media Stream recording.
I have adopted the code example from following link.
https://simpl.info/mediarecorder/
I am basically converting the video file to base64 string and upload that to the server. However, this functionality does not support by our friendly safari browser.
The idea is to use any webcam regardless of device such as Windows or Mac computers or even Ipads. I am developing the site using .net technologies.
Any help would be much appreciated. Please note that it could be a similar thread to others but not duplicate one.
As discussed in the comment, I am attaching the code sample code
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="Simplest possible examples of HTML, CSS and JavaScript." />
<meta name="author" content="//samdutton.com">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<meta itemprop="name" content="simpl.info: simplest possible examples of HTML, CSS and JavaScript">
<meta itemprop="image" content="/images/icons/icon192.png">
<meta name="mobile-web-app-capable" content="yes">
<meta id="theme-color" name="theme-color" content="#fff">
<base target="_blank">
<title>MediaStream Recording</title>
<link rel="canonical" href="https://simpl.info/mediarecorder" />
<link rel="stylesheet" href="../css/main.css" />
<link rel="stylesheet" href="css/main.css" />
</head>
<body>
<div id="container">
<video id="gum" autoplay muted></video>
<video id="recorded" autoplay loop></video>
<div>
<button id="record">Start Recording</button>
<button id="play" disabled>Play</button>
<button id="download" disabled>Download</button>
</div>
</div>
<script src="js/main.js"></script>
<script src="../js/lib/ga.js"></script>
</body>
</html>
Sample JS File
'use strict';
/* globals MediaRecorder */
// This code is adapted from
// https://rawgit.com/Miguelao/demos/master/mediarecorder.html
'use strict';
/* globals MediaRecorder */
// This code is adapted from
// https://rawgit.com/Miguelao/demos/master/mediarecorder.html
var mediaSource = new MediaSource();
mediaSource.addEventListener('sourceopen', handleSourceOpen, false);
var mediaRecorder;
var recordedBlobs;
var sourceBuffer;
var gumVideo = document.querySelector('video#gum');
var recordedVideo = document.querySelector('video#recorded');
var recordButton = document.querySelector('button#record');
var playButton = document.querySelector('button#play');
var downloadButton = document.querySelector('button#download');
recordButton.onclick = toggleRecording;
playButton.onclick = play;
downloadButton.onclick = download;
// window.isSecureContext could be used for Chrome
var isSecureOrigin = location.protocol === 'https:' ||
location.host === 'localhost';
if (!isSecureOrigin) {
alert('getUserMedia() must be run from a secure origin: HTTPS or localhost.' +
'\n\nChanging protocol to HTTPS');
location.protocol = 'HTTPS';
}
// Use old-style gUM to avoid requirement to enable the
// Enable experimental Web Platform features flag in Chrome 49
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
var constraints = {
audio: true,
video: true
};
navigator.getUserMedia(constraints, successCallback, errorCallback);
function successCallback(stream) {
console.log('getUserMedia() got stream: ', stream);
window.stream = stream;
if (window.URL) {
gumVideo.src = window.URL.createObjectURL(stream);
} else {
gumVideo.src = stream;
}
}
function errorCallback(error) {
console.log('navigator.getUserMedia error: ', error);
}
// navigator.mediaDevices.getUserMedia(constraints)
// .then(function(stream) {
// console.log('getUserMedia() got stream: ', stream);
// window.stream = stream; // make available to browser console
// if (window.URL) {
// gumVideo.src = window.URL.createObjectURL(stream);
// } else {
// gumVideo.src = stream;
// }
// }).catch(function(error) {
// console.log('navigator.getUserMedia error: ', error);
// });
function handleSourceOpen(event) {
console.log('MediaSource opened');
sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vp8"');
console.log('Source buffer: ', sourceBuffer);
}
function handleDataAvailable(event) {
if (event.data && event.data.size > 0) {
recordedBlobs.push(event.data);
}
}
function handleStop(event) {
console.log('Recorder stopped: ', event);
}
function toggleRecording() {
if (recordButton.textContent === 'Start Recording') {
startRecording();
} else {
stopRecording();
recordButton.textContent = 'Start Recording';
playButton.disabled = false;
downloadButton.disabled = false;
}
}
// The nested try blocks will be simplified when Chrome 47 moves to Stable
function startRecording() {
var options = {mimeType: 'video/webm', bitsPerSecond: 100000};
recordedBlobs = [];
try {
mediaRecorder = new MediaRecorder(window.stream, options);
} catch (e0) {
console.log('Unable to create MediaRecorder with options Object: ', e0);
try {
options = {mimeType: 'video/webm,codecs=vp9', bitsPerSecond: 100000};
mediaRecorder = new MediaRecorder(window.stream, options);
} catch (e1) {
console.log('Unable to create MediaRecorder with options Object: ', e1);
try {
options = 'video/vp8'; // Chrome 47
mediaRecorder = new MediaRecorder(window.stream, options);
} catch (e2) {
alert('MediaRecorder is not supported by this browser.\n\n' +
'Try Firefox 29 or later, or Chrome 47 or later, with Enable experimental Web Platform features enabled from chrome://flags.');
console.error('Exception while creating MediaRecorder:', e2);
return;
}
}
}
console.log('Created MediaRecorder', mediaRecorder, 'with options', options);
recordButton.textContent = 'Stop Recording';
playButton.disabled = true;
downloadButton.disabled = true;
mediaRecorder.onstop = handleStop;
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.start(10); // collect 10ms of data
console.log('MediaRecorder started', mediaRecorder);
}
function stopRecording() {
mediaRecorder.stop();
console.log('Recorded Blobs: ', recordedBlobs);
recordedVideo.controls = true;
var base64data;
var superBuffer = new Blob(recordedBlobs, {type: 'video/webm'});
var as =window.URL.createObjectURL(superBuffer);
var reader = new window.FileReader();
reader.readAsDataURL(superBuffer);
reader.onloadend = function() {
base64data = reader.result;
console.log(base64data );
document.write(base64data);
}
}
function play() {
var superBuffer = new Blob(recordedBlobs, {type: 'video/webm'});
recordedVideo.src = window.URL.createObjectURL(superBuffer);
}
function download() {
var blob = new Blob(recordedBlobs, {type: 'video/webm'});
var url = window.URL.createObjectURL(blob);
var a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'test.webm';
document.body.appendChild(a);
a.click();
setTimeout(function() {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 100);
}
UPDATE
After reading several documents. I finally found a third party plugin to get WebRTC working in Safari and IE which has been provided by Skylink.
Here is the link - https://confluence.temasys.com.sg/display/TWPP
However, this still does not resolve the overall issue of recording the video it shows streaming but does not provide support to save for later use. I really don't want to use Flash as I then have to buy a flash media server. Is there any other way to do this ?
Like, can I host live stream to somewhere and then provide link to watch it later or convert stream to base64string and store that to the database.
I was pointed to this GITHub sample code by David Fowler himself to track SignalR users and states. I have implemented all of it and it works great except I can't figure out the displaying of Hub connection state changes. I have this which doesn't seem to work. Does anyone know why?
!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<style>
#state {
width: 20px;
height: 50px;
}
</style>
</head>
<body>
<h3 id="msg"></h3>
<div id="state"></div>
<script src="../Scripts/jquery-1.10.2.min.js"></script>
<script src="../Scripts/jquery.signalR-2.0.2.min.js"></script>
<script src="signalr/hubs"></script>
<script>
$(function () {
var userTracking = $.connection.alphaHub;
// Need at least one callback for events to be raised on the hub
userTracking.client.void = function () { };
$.connection.logging = true;
$.connection.hub.stateChanged(function (change) {
if (change.newState === $.signalR.connectionState.connected) {
$('#state').css('background-color', 'green');
} else if (change.newState === $.signalR.connectionState.reconnecting) {
$('#state').css('background-color', 'yellow');
} else if (change.newState === $.signalR.connectionState.disconnected) {
$('#state').css('background-color', 'red');
}
});
$.connection.hub.disconnected(function () {
setTimeout(function () {
$.connection.hub.start();
}, 1000);
});
});
</script>
</body>
</html>
My Hub is shown partially here:
public class AlphaHub : Hub
{
public override async Task OnConnected()
{
try
{
var name = Context.User.Identity.Name;
using (savitasEntities2 entities = new savitasEntities2())
{
var user = entities.SUsers
.Include(u => u.SConnections)
.SingleOrDefault(u => u.UserName == name);
if (user == null)
{
user = new SUser
{
UserName = name,
SConnections = new List<SConnection>()
};
entities.SUsers.Add(user);
}
user.SConnections.Add(new SConnection
{
ConnectionID = Context.ConnectionId,
UserAgent = Context.Request.Headers["User-Agent"],
LastActivity = DateTimeOffset.UtcNow
});
// entities.SaveChanges();
await entities.SaveChangesAsync();
}
}
public override async Task OnDisconnected()
{
try
{
using (savitasEntities2 db = new savitasEntities2())
{
var connection = await db.SConnections.FindAsync(Context.ConnectionId);
db.SConnections.Remove(connection);
await db.SaveChangesAsync();
}
}
catch (Exception ex)
{
c.LogError(ex.Message, "AlphaHub.cs" + " - " + this.GetType().FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name);
}
}
Looks like your hubs can't be found.
Change:
<script src="signalr/hubs"></script>
to:
<script src="~/signalr/hubs"></script>