Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
JavaScriptBridge 싱글톤
웹 빌드에서 JavaScriptBridge 싱글톤는 JavaScript 및 웹 브라우저와의 상호 작용을 허용하고 웹 플랫폼에 고유한 일부 기능을 구현하는 데 사용할 수 있습니다.
쿼터니언(quaternions) 으로 보간하기
때로는 웹용 Godot를 내보낼 때 제3자 SDK, 라이브러리와 같은 외부 JavaScript 코드와 인터페이스하거나 단순히 Godot에서 직접 노출되지 않는 브라우저 기능에 액세스해야 할 수도 있습니다.
JavaScriptBridge 싱글톤는 Godot 스크립팅(예: GDScript 및 C#)의 맥락에서 자연스러운 느낌을 주려고 하는 Godot :ref:`JavaScriptObject <class_JavaScriptObject>`에 기본 JavaScript 객체를 래핑하는 방법을 제공합니다.
JavaScriptBridge.get_interface() 메서드는 전역 범위에서 객체를 검색합니다.
extends Node
func _ready():
# Retrieve the `window.console` object.
var console = JavaScriptBridge.get_interface("console")
# Call the `window.console.log()` method.
console.log("test")
JavaScriptBridge.create_object() <class_JavaScriptBridge_method_create_object>`는 JavaScript ``new` 생성자를 통해 새 객체를 생성합니다.
extends Node
func _ready():
# Call the JavaScript `new` operator on the `window.Array` object.
# Passing 10 as argument to the constructor:
# JS: `new Array(10);`
var arr = JavaScriptBridge.create_object("Array", 10)
# Set the first element of the JavaScript array to the number 42.
arr[0] = 42
# Call the `pop` function on the JavaScript array.
arr.pop()
# Print the value of the `length` property of the array (9 after the pop).
print(arr.length)
보시다시피 JavaScript 개체를 ``JavaScriptObject``로 래핑하면 기본 Godot 개체인 것처럼 상호 작용하고 메서드를 호출하고 속성을 검색(또는 설정)할 수 있습니다.
기본 유형(int, float, string, boolean)은 자동으로 변환됩니다(float는 Godot에서 JavaScript로 변환할 때 정밀도가 떨어질 수 있습니다). 다른 것(예: 객체, 배열, 함수)은 JavaScriptObjects 자체로 표시됩니다.
단점
Godot에서 JavaScript 코드를 호출하는 것은 좋지만 때로는 대신 JavaScript에서 Godot 함수를 호출해야 할 때도 있습니다.
이 경우는 좀 더 복잡합니다. JavaScript는 가비지 수집에 의존하는 반면 Godot는 메모리 관리를 위해 참조 계산을 사용합니다. 즉, 콜백(JavaScriptObjects 자체로 반환됨)을 명시적으로 생성해야 하며 해당 참조를 유지해야 합니다.
JavaScript가 콜백에 전달한 인수는 단일 Godot ``Array``로 전달됩니다.
extends Node
# Here we create a reference to the `_my_callback` function (below).
# This reference will be kept until the node is freed.
var _callback_ref = JavaScriptBridge.create_callback(_my_callback)
func _ready():
# Get the JavaScript `window` object.
var window = JavaScriptBridge.get_interface("window")
# Set the `window.onbeforeunload` DOM event listener.
window.onbeforeunload = _callback_ref
func _my_callback(args):
# Get the first argument (the DOM event in our case).
var js_event = args[0]
# Call preventDefault and set the `returnValue` property of the DOM event.
js_event.preventDefault()
js_event.returnValue = ''
경고
JavaScriptBridge.get_interface() <class_JavaScriptBridge_method_get_interface>`(위 예에서는 ``_my_callback`)를 통해 생성된 콜백 메서드 반드시 정확히 하나의 Array 인수를 취해야 하며, 이는 JavaScript `인수 개체 <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments>`__가 배열. 그렇지 않으면 콜백 메서드가 호출되지 않습니다.
다음은 사용자에게 `알림 권한 <https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API>`__을 요청하고 권한이 부여되면 알림을 전달하기 위해 비동기적으로 기다리는 또 다른 예입니다.
extends Node
# Here we create a reference to the `_on_permissions` function (below).
# This reference will be kept until the node is freed.
var _permission_callback = JavaScriptBridge.create_callback(_on_permissions)
func _ready():
# NOTE: This is done in `_ready` for simplicity, but SHOULD BE done in response
# to user input instead (e.g. during `_input`, or `button_pressed` event, etc.),
# otherwise it might not work.
# Get the `window.Notification` JavaScript object.
var notification = JavaScriptBridge.get_interface("Notification")
# Call the `window.Notification.requestPermission` method which returns a JavaScript
# Promise, and bind our callback to it.
notification.requestPermission().then(_permission_callback)
func _on_permissions(args):
# The first argument of this callback is the string "granted" if the permission is granted.
var permission = args[0]
if permission == "granted":
print("Permission granted, sending notification.")
# Create the notification: `new Notification("Hi there!")`
JavaScriptBridge.create_object("Notification", "Hi there!")
else:
print("No notification permission.")
내가 좋아하는 도서관을 이용할 수 있나요?
아마도 그럴 수 있을 것입니다. 먼저 페이지에 라이브러리를 포함해야 합니다. 내보내는 동안 :ref:`Head 포함 <doc_javascript_export_options>`을 사용자 정의하거나(아래 참조) :ref:`자신만의 템플릿 <doc_customizing_html5_shell>`을 작성할 수도 있습니다.
아래 예에서는 Head Include``를 사용자 정의하여 콘텐츠 전송 네트워크에서 외부 라이브러리(`axios <https://axios-http.com/>`__)를 추가하고 두 번째 ``<script> 태그를 사용자 정의 기능을 정의합니다.
<!-- Axios -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!-- Custom function -->
<script>
function myFunc() {
alert("My func!");
}
</script>
그런 다음 이전 예제에서 했던 것처럼 Godot의 라이브러리와 함수 모두에 접근할 수 있습니다:
extends Node
# Here create a reference to the `_on_get` function (below).
# This reference will be kept until the node is freed.
var _callback = JavaScriptBridge.create_callback(_on_get)
func _ready():
# Get the `window` object, where globally defined functions are.
var window = JavaScriptBridge.get_interface("window")
# Call the JavaScript `myFunc` function defined in the custom HTML head.
window.myFunc()
# Get the `axios` library (loaded from a CDN in the custom HTML head).
var axios = JavaScriptBridge.get_interface("axios")
# Make a GET request to the current location, and receive the callback when done.
axios.get(window.location.toString()).then(_callback)
func _on_get(args):
OS.alert("On Get")
번역 형식
웹 빌드에서 JavaScript 싱글톤이 구현됩니다. eval이라는 하나의 메서드를 제공하는데, 같은 이름의 JavaScript 함수와 비슷하게 작동합니다. 문자열을 인수로 가지며 JavaScript 코드로 실행합니다. 이걸로 Godot와 통합될 수 없는 스크립트 언어를 브라우저와 상호작용할 수 있게됩니다.
func my_func():
JavaScriptBridge.eval("alert('Calling JavaScript per GDScript!');")
private void MyFunc()
{
JavaScriptBridge.Eval("alert('Calling JavaScript per C#!');")
}
마지막 JavaScript 명령문의 값은 GDScript 값으로 변환되며 특정 경우에 eval()에 의해 반환됩니다:
func my_func2():
var js_return = JavaScriptBridge.eval("var myNumber = 1; myNumber + 2;")
print(js_return) # prints '3.0'
private void MyFunc2()
{
var jsReturn = JavaScriptBridge.Eval("var myNumber = 1; myNumber + 2;");
GD.Print(jsReturn); // prints '3.0'
}
다른 JavaScript 값은 null로 반환됩니다.
HTML5 내보내기 템플릿은 보안성을 위해 싱글턴을 지원하지 않고 빌드되었을 수 있습니다. 그런 템플릿의 경우 HTML5 이외의 플랫폼에서 JavaScript.eval를 호출하면 null을 반환합니다. 싱글턴의 지원여부는 아래와 같이 JavaScript 기능 태그로 확인할 수 있습니다:
func my_func3():
if OS.has_feature('web'):
JavaScriptBridge.eval("""
console.log('The JavaScriptBridge singleton is available')
""")
else:
print("The JavaScriptBridge singleton is NOT available")
private void MyFunc3()
{
if (OS.HasFeature("web"))
{
JavaScriptBridge.Eval("console.log('The JavaScriptBridge singleton is available')");
}
else
{
GD.Print("The JavaScriptBridge singleton is NOT available");
}
}
팁
my_func3() 처럼 3개의 큰따옴표 """ 로 둘러싸인 GDScript의 멀티라인 문자열은 JavaScript 코드의 가독성을 높이는데 유용합니다.
eval 메서드는 두번째 옵션인 Boolean 인자도 받으며 이 인자는 전역 실행 컨텍스트에서 코드를 실행하는 것들을 지정합니다, 전역 네임스페이스가 오염되지않기 위해 기본적으로 false입니다:
func my_func4():
# execute in global execution context,
# thus adding a new JavaScript global variable `SomeGlobal`
JavaScriptBridge.eval("var SomeGlobal = {};", true)
private void MyFunc4()
{
// execute in global execution context,
// thus adding a new JavaScript global variable `SomeGlobal`
JavaScriptBridge.Eval("var SomeGlobal = {};", true);
}
다운로드
Godot 웹 내보내기에서 사용자 컴퓨터로 파일(예: 저장 게임)을 다운로드하는 것은 JavaScript와 직접 상호 작용하여 수행할 수 있지만 매우 일반적인 사용 사례인 경우 Godot는 생성된 버퍼를 다운로드할 수 있는 전용 JavaScriptBridge.download_buffer() 함수를 통해 이 기능을 스크립팅에 노출합니다.
어떻게 작동하는 지의 예제입니다:
extends
func _ready():
# Asks the user download a file called "hello.txt" whose content will be the string "Hello".
JavaScriptBridge.download_buffer("Hello".to_utf8_buffer(), "hello.txt")
다음은 이전에 저장한 파일을 다운로드하는 방법에 대한 보다 완전한 예입니다.
extends Node
# Open a file for reading and download it via the JavaScript singleton.
func _download_file(path):
var file = FileAccess.open(path, FileAccess.READ)
if file == null:
push_error("Failed to load file")
return
# Get the file name.
var fname = path.get_file()
# Read the whole file to memory.
var buffer = file.get_buffer(file.get_len())
# Prompt the user to download the file (will have the same name as the input file).
JavaScriptBridge.download_buffer(buffer, fname)
func _ready():
# Create a temporary file.
var config = ConfigFile.new()
config.set_value("option", "one", false)
config.save("/tmp/test.cfg")
# Download it
_download_file("/tmp/test.cfg")